Drop CECPQ2b code.
The experiment which motivated CECPQ2b has concluded (although the
results haven't been published yet) and the SIKE code is causing some
issues for gRPC in gprc/grpc#20100. Also, this is code size that takes
up space in Android etc.
Change-Id: I43b0b8c420f236c0fe9b40bf2517d2fde98495d5
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/38384
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc
index 58f0f8a..1ec596a 100644
--- a/ssl/s3_both.cc
+++ b/ssl/s3_both.cc
@@ -660,8 +660,7 @@
public:
CipherScorer(uint16_t group_id)
: aes_is_fine_(EVP_has_aes_hardware()),
- security_128_is_fine_(group_id != SSL_CURVE_CECPQ2 &&
- group_id != SSL_CURVE_CECPQ2b) {}
+ security_128_is_fine_(group_id != SSL_CURVE_CECPQ2) {}
typedef std::tuple<bool, bool, bool> Score;
diff --git a/ssl/ssl_key_share.cc b/ssl/ssl_key_share.cc
index 826fb1a..6cac3cf 100644
--- a/ssl/ssl_key_share.cc
+++ b/ssl/ssl_key_share.cc
@@ -31,7 +31,6 @@
#include "internal.h"
#include "../crypto/internal.h"
-#include "../third_party/sike/sike.h"
BSSL_NAMESPACE_BEGIN
@@ -300,87 +299,6 @@
HRSS_private_key hrss_private_key_;
};
-class CECPQ2bKeyShare : public SSLKeyShare {
- public:
- uint16_t GroupID() const override { return SSL_CURVE_CECPQ2b; }
-
- bool Offer(CBB *out) override {
- uint8_t public_x25519[32] = {0};
- X25519_keypair(public_x25519, private_x25519_);
- if (!SIKE_keypair(private_sike_, public_sike_)) {
- return false;
- }
-
- return CBB_add_bytes(out, public_x25519, sizeof(public_x25519)) &&
- CBB_add_bytes(out, public_sike_, sizeof(public_sike_));
- }
-
- bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
- uint8_t *out_alert, Span<const uint8_t> peer_key) override {
- uint8_t public_x25519[32];
- uint8_t private_x25519[32];
- uint8_t sike_ciphertext[SIKE_CT_BYTESZ] = {0};
-
- *out_alert = SSL_AD_INTERNAL_ERROR;
-
- if (peer_key.size() != sizeof(public_x25519) + SIKE_PUB_BYTESZ) {
- *out_alert = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
- return false;
- }
-
- Array<uint8_t> secret;
- if (!secret.Init(sizeof(private_x25519_) + SIKE_SS_BYTESZ)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return false;
- }
-
- X25519_keypair(public_x25519, private_x25519);
- if (!X25519(secret.data(), private_x25519, peer_key.data())) {
- *out_alert = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
- return false;
- }
-
- SIKE_encaps(secret.data() + sizeof(private_x25519_), sike_ciphertext,
- peer_key.data() + sizeof(public_x25519));
- *out_secret = std::move(secret);
-
- return CBB_add_bytes(out_public_key, public_x25519,
- sizeof(public_x25519)) &&
- CBB_add_bytes(out_public_key, sike_ciphertext,
- sizeof(sike_ciphertext));
- }
-
- bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
- Span<const uint8_t> peer_key) override {
- *out_alert = SSL_AD_INTERNAL_ERROR;
-
- Array<uint8_t> secret;
- if (!secret.Init(sizeof(private_x25519_) + SIKE_SS_BYTESZ)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return false;
- }
-
- if (peer_key.size() != 32 + SIKE_CT_BYTESZ ||
- !X25519(secret.data(), private_x25519_, peer_key.data())) {
- *out_alert = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
- return false;
- }
-
- SIKE_decaps(secret.data() + sizeof(private_x25519_), peer_key.data() + 32,
- public_sike_, private_sike_);
- *out_secret = std::move(secret);
- return true;
- }
-
- private:
- uint8_t private_x25519_[32];
- uint8_t private_sike_[SIKE_PRV_BYTESZ];
- uint8_t public_sike_[SIKE_PUB_BYTESZ];
-};
-
CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
{NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
{NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
@@ -388,7 +306,6 @@
{NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
{NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
{NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
- {NID_CECPQ2b, SSL_CURVE_CECPQ2b, "CECPQ2b", "CECPQ2b"},
};
} // namespace
@@ -415,8 +332,6 @@
return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
case SSL_CURVE_CECPQ2:
return UniquePtr<SSLKeyShare>(New<CECPQ2KeyShare>());
- case SSL_CURVE_CECPQ2b:
- return UniquePtr<SSLKeyShare>(New<CECPQ2bKeyShare>());
default:
return nullptr;
}
diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc
index cc29a83..e5a33dd 100644
--- a/ssl/t1_lib.cc
+++ b/ssl/t1_lib.cc
@@ -200,7 +200,7 @@
}
static bool is_post_quantum_group(uint16_t id) {
- return id == SSL_CURVE_CECPQ2 || id == SSL_CURVE_CECPQ2b;
+ return id == SSL_CURVE_CECPQ2;
}
bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out,
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index d1cf757..a4f787a 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -151,7 +151,6 @@
CurveP521 CurveID = 25
CurveX25519 CurveID = 29
CurveCECPQ2 CurveID = 16696
- CurveCECPQ2b CurveID = 65074
)
// TLS Elliptic Curve Point Formats
@@ -1732,7 +1731,7 @@
return ret
}
-var defaultCurvePreferences = []CurveID{CurveCECPQ2b, CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
+var defaultCurvePreferences = []CurveID{CurveCECPQ2, CurveX25519, CurveP256, CurveP384, CurveP521}
func (c *Config) curvePreferences() []CurveID {
if c == nil || len(c.CurvePreferences) == 0 {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 44b817e..2427856 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -210,7 +210,7 @@
if config.Bugs.FailIfCECPQ2Offered {
for _, offeredCurve := range hs.clientHello.supportedCurves {
if isPqGroup(offeredCurve) {
- return errors.New("tls: CECPQ2 or CECPQ2b was offered")
+ return errors.New("tls: CECPQ2 was offered")
}
}
}
@@ -1227,7 +1227,7 @@
Curves:
for _, curve := range hs.clientHello.supportedCurves {
if isPqGroup(curve) && c.vers < VersionTLS13 {
- // CECPQ2 and CECPQ2b is TLS 1.3-only.
+ // CECPQ2 is TLS 1.3-only.
continue
}
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 56cfec8..266163e 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -19,7 +19,6 @@
"boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519"
"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
- "boringssl.googlesource.com/boringssl/ssl/test/runner/sike"
)
type keyType int
@@ -434,98 +433,6 @@
return preMasterSecret, nil
}
-// cecpq2BCurve implements CECPQ2b, which is SIKE combined with X25519.
-type cecpq2BCurve struct {
- // Both public key and shared secret size
- x25519PrivateKey [32]byte
- sikePrivateKey *sike.PrivateKey
-}
-
-func (e *cecpq2BCurve) offer(rand io.Reader) (publicKey []byte, err error) {
- if _, err = io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
- return nil, err
- }
-
- var x25519Public [32]byte
- curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
-
- e.sikePrivateKey = sike.NewPrivateKey(sike.KeyVariant_SIKE)
- if err = e.sikePrivateKey.Generate(rand); err != nil {
- return nil, err
- }
-
- sikePublic := e.sikePrivateKey.GeneratePublicKey().Export()
- var ret []byte
- ret = append(ret, x25519Public[:]...)
- ret = append(ret, sikePublic...)
- return ret, nil
-}
-
-func (e *cecpq2BCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
- if len(peerKey) != 32+sike.Params.PublicKeySize {
- return nil, nil, errors.New("tls: bad length CECPQ2b offer")
- }
-
- if _, err = io.ReadFull(rand, e.x25519PrivateKey[:]); err != nil {
- return nil, nil, err
- }
-
- var x25519Shared, x25519PeerKey, x25519Public [32]byte
- copy(x25519PeerKey[:], peerKey)
- curve25519.ScalarBaseMult(&x25519Public, &e.x25519PrivateKey)
- curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
-
- // Per RFC 7748, reject the all-zero value in constant time.
- var zeros [32]byte
- if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
- return nil, nil, errors.New("tls: X25519 value with wrong order")
- }
-
- var sikePubKey = sike.NewPublicKey(sike.KeyVariant_SIKE)
- if err = sikePubKey.Import(peerKey[32:]); err != nil {
- // should never happen as size was already checked
- return nil, nil, errors.New("tls: implementation error")
- }
- sikeCiphertext, sikeShared, err := sike.Encapsulate(rand, sikePubKey)
- if err != nil {
- return nil, nil, err
- }
-
- publicKey = append(publicKey, x25519Public[:]...)
- publicKey = append(publicKey, sikeCiphertext...)
- preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
- preMasterSecret = append(preMasterSecret, sikeShared...)
-
- return publicKey, preMasterSecret, nil
-}
-
-func (e *cecpq2BCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
- if len(peerKey) != 32+(sike.Params.PublicKeySize+sike.Params.MsgLen) {
- return nil, errors.New("tls: bad length CECPQ2b reply")
- }
-
- var x25519Shared, x25519PeerKey [32]byte
- copy(x25519PeerKey[:], peerKey)
- curve25519.ScalarMult(&x25519Shared, &e.x25519PrivateKey, &x25519PeerKey)
-
- // Per RFC 7748, reject the all-zero value in constant time.
- var zeros [32]byte
- if subtle.ConstantTimeCompare(zeros[:], x25519Shared[:]) == 1 {
- return nil, errors.New("tls: X25519 value with wrong order")
- }
-
- var sikePubKey = e.sikePrivateKey.GeneratePublicKey()
- sikeShared, err := sike.Decapsulate(e.sikePrivateKey, sikePubKey, peerKey[32:])
- if err != nil {
- return nil, errors.New("tls: invalid SIKE ciphertext")
- }
-
- preMasterSecret = append(preMasterSecret, x25519Shared[:]...)
- preMasterSecret = append(preMasterSecret, sikeShared...)
-
- return preMasterSecret, nil
-}
-
func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) {
switch id {
case CurveP224:
@@ -540,8 +447,6 @@
return &x25519ECDHCurve{setHighBit: config.Bugs.SetX25519HighBit}, true
case CurveCECPQ2:
return &cecpq2Curve{}, true
- case CurveCECPQ2b:
- return &cecpq2BCurve{}, true
default:
return nil, false
}
@@ -690,7 +595,7 @@
NextCandidate:
for _, candidate := range preferredCurves {
if isPqGroup(candidate) && version < VersionTLS13 {
- // CECPQ2 and CECPQ2b is TLS 1.3-only.
+ // CECPQ2 is TLS 1.3-only.
continue
}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 758566a..18b01aa 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -10449,13 +10449,12 @@
{"P-521", CurveP521},
{"X25519", CurveX25519},
{"CECPQ2", CurveCECPQ2},
- {"CECPQ2b", CurveCECPQ2b},
}
const bogusCurve = 0x1234
func isPqGroup(r CurveID) bool {
- return r == CurveCECPQ2 || r == CurveCECPQ2b
+ return r == CurveCECPQ2
}
func addCurveTests() {
@@ -10928,21 +10927,6 @@
},
})
- // CECPQ2b should not be offered by a TLS < 1.3 client.
- testCases = append(testCases, testCase{
- name: "CECPQ2bNotInTLS12",
- config: Config{
- Bugs: ProtocolBugs{
- FailIfCECPQ2Offered: true,
- },
- },
- flags: []string{
- "-max-version", strconv.Itoa(VersionTLS12),
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-curves", strconv.Itoa(int(CurveX25519)),
- },
- })
-
// CECPQ2 should not crash a TLS < 1.3 client if the server mistakenly
// selects it.
testCases = append(testCases, testCase{
@@ -10961,24 +10945,6 @@
expectedError: ":WRONG_CURVE:",
})
- // CECPQ2b should not crash a TLS < 1.3 client if the server mistakenly
- // selects it.
- testCases = append(testCases, testCase{
- name: "CECPQ2bNotAcceptedByTLS12Client",
- config: Config{
- Bugs: ProtocolBugs{
- SendCurve: CurveCECPQ2b,
- },
- },
- flags: []string{
- "-max-version", strconv.Itoa(VersionTLS12),
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-curves", strconv.Itoa(int(CurveX25519)),
- },
- shouldFail: true,
- expectedError: ":WRONG_CURVE:",
- })
-
// CECPQ2 should not be offered by default as a client.
testCases = append(testCases, testCase{
name: "CECPQ2NotEnabledByDefaultInClients",
@@ -10990,17 +10956,6 @@
},
})
- // CECPQ2b should not be offered by default as a client.
- testCases = append(testCases, testCase{
- name: "CECPQ2bNotEnabledByDefaultInClients",
- config: Config{
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- FailIfCECPQ2Offered: true,
- },
- },
- })
-
// If CECPQ2 is offered, both X25519 and CECPQ2 should have a key-share.
testCases = append(testCases, testCase{
name: "NotJustCECPQ2KeyShare",
@@ -11033,38 +10988,6 @@
},
})
- // If CECPQ2b is offered, both X25519 and CECPQ2b should have a key-share.
- testCases = append(testCases, testCase{
- name: "NotJustCECPQ2bKeyShare",
- config: Config{
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectedKeyShares: []CurveID{CurveCECPQ2b, CurveX25519},
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-curves", strconv.Itoa(int(CurveX25519)),
- "-expect-curve-id", strconv.Itoa(int(CurveCECPQ2b)),
- },
- })
-
- // ... but only if CECPQ2b is listed first.
- testCases = append(testCases, testCase{
- name: "CECPQ2bKeyShareNotIncludedSecond",
- config: Config{
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectedKeyShares: []CurveID{CurveX25519},
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveX25519)),
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-expect-curve-id", strconv.Itoa(int(CurveX25519)),
- },
- })
-
// If CECPQ2 is the only configured curve, the key share is sent.
testCases = append(testCases, testCase{
name: "JustConfiguringCECPQ2Works",
@@ -11080,21 +11003,6 @@
},
})
- // If CECPQ2b is the only configured curve, the key share is sent.
- testCases = append(testCases, testCase{
- name: "JustConfiguringCECPQ2bWorks",
- config: Config{
- MinVersion: VersionTLS13,
- Bugs: ProtocolBugs{
- ExpectedKeyShares: []CurveID{CurveCECPQ2b},
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-expect-curve-id", strconv.Itoa(int(CurveCECPQ2b)),
- },
- })
-
// As a server, CECPQ2 is not yet supported by default.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -11109,21 +11017,6 @@
"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
},
})
-
- // As a server, CECPQ2b is not yet supported by default.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "CECPQ2bNotEnabledByDefaultForAServer",
- config: Config{
- MinVersion: VersionTLS13,
- CurvePreferences: []CurveID{CurveCECPQ2b, CurveX25519},
- DefaultCurves: []CurveID{CurveCECPQ2b},
- },
- flags: []string{
- "-server-preference",
- "-expect-curve-id", strconv.Itoa(int(CurveX25519)),
- },
- })
}
func addTLS13RecordTests() {
@@ -14049,21 +13942,6 @@
},
})
- // CECPQ2b prefers 256-bit ciphers but will use AES-128 if there's nothing else.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TLS13-CipherPreference-CECPQ2b-AES128Only",
- config: Config{
- MaxVersion: VersionTLS13,
- CipherSuites: []uint16{
- TLS_AES_128_GCM_SHA256,
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- },
- })
-
// When a 256-bit cipher is offered, even if not in first place, it should be
// picked.
testCases = append(testCases, testCase{
@@ -14098,40 +13976,6 @@
expectedCipher: TLS_AES_128_GCM_SHA256,
})
- // When a 256-bit cipher is offered, even if not in first place, it should be
- // picked.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TLS13-CipherPreference-CECPQ2b-AES256Preferred",
- config: Config{
- MaxVersion: VersionTLS13,
- CipherSuites: []uint16{
- TLS_AES_128_GCM_SHA256,
- TLS_AES_256_GCM_SHA384,
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- },
- expectedCipher: TLS_AES_256_GCM_SHA384,
- })
- // ... but when CECPQ2b isn't being used, the client's preference controls.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TLS13-CipherPreference-CECPQ2b-AES128PreferredOtherwise",
- config: Config{
- MaxVersion: VersionTLS13,
- CipherSuites: []uint16{
- TLS_AES_128_GCM_SHA256,
- TLS_AES_256_GCM_SHA384,
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveX25519)),
- },
- expectedCipher: TLS_AES_128_GCM_SHA256,
- })
-
// Test that CECPQ2 continues to honor AES vs ChaCha20 logic.
testCases = append(testCases, testCase{
testType: serverTest,
@@ -14167,42 +14011,6 @@
"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
},
})
-
- // Test that CECPQ2b continues to honor AES vs ChaCha20 logic.
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TLS13-CipherPreference-CECPQ2b-AES128-ChaCha20-AES256",
- config: Config{
- MaxVersion: VersionTLS13,
- CipherSuites: []uint16{
- TLS_AES_128_GCM_SHA256,
- TLS_CHACHA20_POLY1305_SHA256,
- TLS_AES_256_GCM_SHA384,
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
- "-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
- },
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "TLS13-CipherPreference-CECPQ2b-AES128-AES256-ChaCha20",
- config: Config{
- MaxVersion: VersionTLS13,
- CipherSuites: []uint16{
- TLS_AES_128_GCM_SHA256,
- TLS_AES_256_GCM_SHA384,
- TLS_CHACHA20_POLY1305_SHA256,
- },
- },
- flags: []string{
- "-curves", strconv.Itoa(int(CurveCECPQ2b)),
- "-expect-cipher-aes", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
- "-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
- },
- })
}
func addPeekTests() {
diff --git a/ssl/test/runner/sike/arith.go b/ssl/test/runner/sike/arith.go
deleted file mode 100644
index 10a2ca6..0000000
--- a/ssl/test/runner/sike/arith.go
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright (c) 2019, Cloudflare Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package sike
-
-import (
- "math/bits"
-)
-
-// Compute z = x + y (mod 2*p).
-func fpAddRdc(z, x, y *Fp) {
- var carry uint64
-
- // z=x+y % p
- for i := 0; i < FP_WORDS; i++ {
- z[i], carry = bits.Add64(x[i], y[i], carry)
- }
-
- // z = z - pX2
- carry = 0
- for i := 0; i < FP_WORDS; i++ {
- z[i], carry = bits.Sub64(z[i], pX2[i], carry)
- }
-
- // if z<0 add pX2 back
- mask := uint64(0 - carry)
- carry = 0
- for i := 0; i < FP_WORDS; i++ {
- z[i], carry = bits.Add64(z[i], pX2[i]&mask, carry)
- }
-}
-
-// Compute z = x - y (mod 2*p).
-func fpSubRdc(z, x, y *Fp) {
- var borrow uint64
-
- // z = z - pX2
- for i := 0; i < FP_WORDS; i++ {
- z[i], borrow = bits.Sub64(x[i], y[i], borrow)
- }
-
- // if z<0 add pX2 back
- mask := uint64(0 - borrow)
- borrow = 0
- for i := 0; i < FP_WORDS; i++ {
- z[i], borrow = bits.Add64(z[i], pX2[i]&mask, borrow)
- }
-}
-
-// Reduce a field element in [0, 2*p) to one in [0,p).
-func fpRdcP(x *Fp) {
- var borrow, mask uint64
- for i := 0; i < FP_WORDS; i++ {
- x[i], borrow = bits.Sub64(x[i], p[i], borrow)
- }
-
- // Sets all bits if borrow = 1
- mask = 0 - borrow
- borrow = 0
- for i := 0; i < FP_WORDS; i++ {
- x[i], borrow = bits.Add64(x[i], p[i]&mask, borrow)
- }
-}
-
-// Implementation doesn't actually depend on a prime field.
-func fpSwapCond(x, y *Fp, mask uint8) {
- if mask != 0 {
- var tmp Fp
- copy(tmp[:], y[:])
- copy(y[:], x[:])
- copy(x[:], tmp[:])
- }
-}
-
-// Compute z = x * y.
-func fpMul(z *FpX2, x, y *Fp) {
- var carry, t, u, v uint64
- var hi, lo uint64
-
- for i := uint64(0); i < FP_WORDS; i++ {
- for j := uint64(0); j <= i; j++ {
- hi, lo = bits.Mul64(x[j], y[i-j])
- v, carry = bits.Add64(lo, v, 0)
- u, carry = bits.Add64(hi, u, carry)
- t += carry
- }
- z[i] = v
- v = u
- u = t
- t = 0
- }
-
- for i := FP_WORDS; i < (2*FP_WORDS)-1; i++ {
- for j := i - FP_WORDS + 1; j < FP_WORDS; j++ {
- hi, lo = bits.Mul64(x[j], y[i-j])
- v, carry = bits.Add64(lo, v, 0)
- u, carry = bits.Add64(hi, u, carry)
- t += carry
- }
- z[i] = v
- v = u
- u = t
- t = 0
- }
- z[2*FP_WORDS-1] = v
-}
-
-// Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
-// with R=2^512. Destroys the input value.
-func fpMontRdc(z *Fp, x *FpX2) {
- var carry, t, u, v uint64
- var hi, lo uint64
- var count int
-
- count = 3 // number of 0 digits in the least significat part of p + 1
-
- for i := 0; i < FP_WORDS; i++ {
- for j := 0; j < i; j++ {
- if j < (i - count + 1) {
- hi, lo = bits.Mul64(z[j], p1[i-j])
- v, carry = bits.Add64(lo, v, 0)
- u, carry = bits.Add64(hi, u, carry)
- t += carry
- }
- }
- v, carry = bits.Add64(v, x[i], 0)
- u, carry = bits.Add64(u, 0, carry)
- t += carry
-
- z[i] = v
- v = u
- u = t
- t = 0
- }
-
- for i := FP_WORDS; i < 2*FP_WORDS-1; i++ {
- if count > 0 {
- count--
- }
- for j := i - FP_WORDS + 1; j < FP_WORDS; j++ {
- if j < (FP_WORDS - count) {
- hi, lo = bits.Mul64(z[j], p1[i-j])
- v, carry = bits.Add64(lo, v, 0)
- u, carry = bits.Add64(hi, u, carry)
- t += carry
- }
- }
- v, carry = bits.Add64(v, x[i], 0)
- u, carry = bits.Add64(u, 0, carry)
-
- t += carry
- z[i-FP_WORDS] = v
- v = u
- u = t
- t = 0
- }
- v, carry = bits.Add64(v, x[2*FP_WORDS-1], 0)
- z[FP_WORDS-1] = v
-}
-
-// Compute z = x + y, without reducing mod p.
-func fp2Add(z, x, y *FpX2) {
- var carry uint64
- for i := 0; i < 2*FP_WORDS; i++ {
- z[i], carry = bits.Add64(x[i], y[i], carry)
- }
-}
-
-// Compute z = x - y, without reducing mod p.
-func fp2Sub(z, x, y *FpX2) {
- var borrow, mask uint64
- for i := 0; i < 2*FP_WORDS; i++ {
- z[i], borrow = bits.Sub64(x[i], y[i], borrow)
- }
-
- // Sets all bits if borrow = 1
- mask = 0 - borrow
- borrow = 0
- for i := FP_WORDS; i < 2*FP_WORDS; i++ {
- z[i], borrow = bits.Add64(z[i], p[i-FP_WORDS]&mask, borrow)
- }
-}
-
-// Montgomery multiplication. Input values must be already
-// in Montgomery domain.
-func fpMulRdc(dest, lhs, rhs *Fp) {
- a := lhs // = a*R
- b := rhs // = b*R
-
- var ab FpX2
- fpMul(&ab, a, b) // = a*b*R*R
- fpMontRdc(dest, &ab) // = a*b*R mod p
-}
-
-// Set dest = x^((p-3)/4). If x is square, this is 1/sqrt(x).
-// Uses variation of sliding-window algorithm from with window size
-// of 5 and least to most significant bit sliding (left-to-right)
-// See HAC 14.85 for general description.
-//
-// Allowed to overlap x with dest.
-// All values in Montgomery domains
-// Set dest = x^(2^k), for k >= 1, by repeated squarings.
-func p34(dest, x *Fp) {
- var lookup [16]Fp
-
- // This performs sum(powStrategy) + 1 squarings and len(lookup) + len(mulStrategy)
- // multiplications.
- powStrategy := []uint8{
- 0x03, 0x0A, 0x07, 0x05, 0x06, 0x05, 0x03, 0x08, 0x04, 0x07,
- 0x05, 0x06, 0x04, 0x05, 0x09, 0x06, 0x03, 0x0B, 0x05, 0x05,
- 0x02, 0x08, 0x04, 0x07, 0x07, 0x08, 0x05, 0x06, 0x04, 0x08,
- 0x05, 0x02, 0x0A, 0x06, 0x05, 0x04, 0x08, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x01}
- mulStrategy := []uint8{
- 0x02, 0x0F, 0x09, 0x08, 0x0E, 0x0C, 0x02, 0x08, 0x05, 0x0F,
- 0x08, 0x0F, 0x06, 0x06, 0x03, 0x02, 0x00, 0x0A, 0x09, 0x0D,
- 0x01, 0x0C, 0x03, 0x07, 0x01, 0x0A, 0x08, 0x0B, 0x02, 0x0F,
- 0x0E, 0x01, 0x0B, 0x0C, 0x0E, 0x03, 0x0B, 0x0F, 0x0F, 0x0F,
- 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
- 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
- 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
- 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00}
- initialMul := uint8(8)
-
- // Precompute lookup table of odd multiples of x for window
- // size k=5.
- var xx Fp
- fpMulRdc(&xx, x, x)
- lookup[0] = *x
- for i := 1; i < 16; i++ {
- fpMulRdc(&lookup[i], &lookup[i-1], &xx)
- }
-
- // Now lookup = {x, x^3, x^5, ... }
- // so that lookup[i] = x^{2*i + 1}
- // so that lookup[k/2] = x^k, for odd k
- *dest = lookup[initialMul]
- for i := uint8(0); i < uint8(len(powStrategy)); i++ {
- fpMulRdc(dest, dest, dest)
- for j := uint8(1); j < powStrategy[i]; j++ {
- fpMulRdc(dest, dest, dest)
- }
- fpMulRdc(dest, dest, &lookup[mulStrategy[i]])
- }
-}
-
-func add(dest, lhs, rhs *Fp2) {
- fpAddRdc(&dest.A, &lhs.A, &rhs.A)
- fpAddRdc(&dest.B, &lhs.B, &rhs.B)
-}
-
-func sub(dest, lhs, rhs *Fp2) {
- fpSubRdc(&dest.A, &lhs.A, &rhs.A)
- fpSubRdc(&dest.B, &lhs.B, &rhs.B)
-}
-
-func mul(dest, lhs, rhs *Fp2) {
- // Let (a,b,c,d) = (lhs.a,lhs.b,rhs.a,rhs.b).
- a := &lhs.A
- b := &lhs.B
- c := &rhs.A
- d := &rhs.B
-
- // We want to compute
- //
- // (a + bi)*(c + di) = (a*c - b*d) + (a*d + b*c)i
- //
- // Use Karatsuba's trick: note that
- //
- // (b - a)*(c - d) = (b*c + a*d) - a*c - b*d
- //
- // so (a*d + b*c) = (b-a)*(c-d) + a*c + b*d.
-
- var ac, bd FpX2
- fpMul(&ac, a, c) // = a*c*R*R
- fpMul(&bd, b, d) // = b*d*R*R
-
- var b_minus_a, c_minus_d Fp
- fpSubRdc(&b_minus_a, b, a) // = (b-a)*R
- fpSubRdc(&c_minus_d, c, d) // = (c-d)*R
-
- var ad_plus_bc FpX2
- fpMul(&ad_plus_bc, &b_minus_a, &c_minus_d) // = (b-a)*(c-d)*R*R
- fp2Add(&ad_plus_bc, &ad_plus_bc, &ac) // = ((b-a)*(c-d) + a*c)*R*R
- fp2Add(&ad_plus_bc, &ad_plus_bc, &bd) // = ((b-a)*(c-d) + a*c + b*d)*R*R
-
- fpMontRdc(&dest.B, &ad_plus_bc) // = (a*d + b*c)*R mod p
-
- var ac_minus_bd FpX2
- fp2Sub(&ac_minus_bd, &ac, &bd) // = (a*c - b*d)*R*R
- fpMontRdc(&dest.A, &ac_minus_bd) // = (a*c - b*d)*R mod p
-}
-
-func inv(dest, x *Fp2) {
- var a2PlusB2 Fp
- var asq, bsq FpX2
- var ac FpX2
- var minusB Fp
- var minusBC FpX2
-
- a := &x.A
- b := &x.B
-
- // We want to compute
- //
- // 1 1 (a - bi) (a - bi)
- // -------- = -------- -------- = -----------
- // (a + bi) (a + bi) (a - bi) (a^2 + b^2)
- //
- // Letting c = 1/(a^2 + b^2), this is
- //
- // 1/(a+bi) = a*c - b*ci.
-
- fpMul(&asq, a, a) // = a*a*R*R
- fpMul(&bsq, b, b) // = b*b*R*R
- fp2Add(&asq, &asq, &bsq) // = (a^2 + b^2)*R*R
- fpMontRdc(&a2PlusB2, &asq) // = (a^2 + b^2)*R mod p
- // Now a2PlusB2 = a^2 + b^2
-
- inv := a2PlusB2
- fpMulRdc(&inv, &a2PlusB2, &a2PlusB2)
- p34(&inv, &inv)
- fpMulRdc(&inv, &inv, &inv)
- fpMulRdc(&inv, &inv, &a2PlusB2)
-
- fpMul(&ac, a, &inv)
- fpMontRdc(&dest.A, &ac)
-
- fpSubRdc(&minusB, &minusB, b)
- fpMul(&minusBC, &minusB, &inv)
- fpMontRdc(&dest.B, &minusBC)
-}
-
-func sqr(dest, x *Fp2) {
- var a2, aPlusB, aMinusB Fp
- var a2MinB2, ab2 FpX2
-
- a := &x.A
- b := &x.B
-
- // (a + bi)*(a + bi) = (a^2 - b^2) + 2abi.
- fpAddRdc(&a2, a, a) // = a*R + a*R = 2*a*R
- fpAddRdc(&aPlusB, a, b) // = a*R + b*R = (a+b)*R
- fpSubRdc(&aMinusB, a, b) // = a*R - b*R = (a-b)*R
- fpMul(&a2MinB2, &aPlusB, &aMinusB) // = (a+b)*(a-b)*R*R = (a^2 - b^2)*R*R
- fpMul(&ab2, &a2, b) // = 2*a*b*R*R
- fpMontRdc(&dest.A, &a2MinB2) // = (a^2 - b^2)*R mod p
- fpMontRdc(&dest.B, &ab2) // = 2*a*b*R mod p
-}
-
-// In case choice == 1, performs following swap in constant time:
-// xPx <-> xQx
-// xPz <-> xQz
-// Otherwise returns xPx, xPz, xQx, xQz unchanged
-func condSwap(xPx, xPz, xQx, xQz *Fp2, choice uint8) {
- fpSwapCond(&xPx.A, &xQx.A, choice)
- fpSwapCond(&xPx.B, &xQx.B, choice)
- fpSwapCond(&xPz.A, &xQz.A, choice)
- fpSwapCond(&xPz.B, &xQz.B, choice)
-}
diff --git a/ssl/test/runner/sike/consts.go b/ssl/test/runner/sike/consts.go
deleted file mode 100644
index 9d68a4f..0000000
--- a/ssl/test/runner/sike/consts.go
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright (c) 2019, Cloudflare Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package sike
-
-// I keep it bool in order to be able to apply logical NOT
-type KeyVariant uint
-
-// Representation of an element of the base field F_p.
-//
-// No particular meaning is assigned to the representation -- it could represent
-// an element in Montgomery form, or not. Tracking the meaning of the field
-// element is left to higher types.
-type Fp [FP_WORDS]uint64
-
-// Represents an intermediate product of two elements of the base field F_p.
-type FpX2 [2 * FP_WORDS]uint64
-
-// Represents an element of the extended field Fp^2 = Fp(x+i)
-type Fp2 struct {
- A Fp
- B Fp
-}
-
-type DomainParams struct {
- // P, Q and R=P-Q base points
- Affine_P, Affine_Q, Affine_R Fp2
- // Size of a compuatation strategy for x-torsion group
- IsogenyStrategy []uint32
- // Max size of secret key for x-torsion group
- SecretBitLen uint
- // Max size of secret key for x-torsion group
- SecretByteLen uint
-}
-
-type SidhParams struct {
- Id uint8
- // Bytelen of P
- Bytelen int
- // The public key size, in bytes.
- PublicKeySize int
- // The shared secret size, in bytes.
- SharedSecretSize int
- // Defines A,C constant for starting curve Cy^2 = x^3 + Ax^2 + x
- InitCurve ProjectiveCurveParameters
- // 2- and 3-torsion group parameter definitions
- A, B DomainParams
- // Precomputed 1/2 in the Fp2 in Montgomery domain
- HalfFp2 Fp2
- // Precomputed identity element in the Fp2 in Montgomery domain
- OneFp2 Fp2
- // Length of SIKE secret message. Must be one of {24,32,40},
- // depending on size of prime field used (see [SIKE], 1.4 and 5.1)
- MsgLen int
- // Length of SIKE ephemeral KEM key (see [SIKE], 1.4 and 5.1)
- KemSize int
- // Size of a ciphertext returned by encapsulation in bytes
- CiphertextSize int
-}
-
-// Stores curve projective parameters equivalent to A/C. Meaning of the
-// values depends on the context. When working with isogenies over
-// subgroup that are powers of:
-// * three then (A:C) ~ (A+2C:A-2C)
-// * four then (A:C) ~ (A+2C: 4C)
-// See Appendix A of SIKE for more details
-type CurveCoefficientsEquiv struct {
- A Fp2
- C Fp2
-}
-
-// A point on the projective line P^1(F_{p^2}).
-//
-// This represents a point on the Kummer line of a Montgomery curve. The
-// curve is specified by a ProjectiveCurveParameters struct.
-type ProjectivePoint struct {
- X Fp2
- Z Fp2
-}
-
-// Base type for public and private key. Used mainly to carry domain
-// parameters.
-type key struct {
- // Domain parameters of the algorithm to be used with a key
- params *SidhParams
- // Flag indicates whether corresponds to 2-, 3-torsion group or SIKE
- keyVariant KeyVariant
-}
-
-// Defines operations on private key
-type PrivateKey struct {
- key
- // Secret key
- Scalar []byte
- // Used only by KEM
- S []byte
-}
-
-// Defines operations on public key
-type PublicKey struct {
- key
- affine_xP Fp2
- affine_xQ Fp2
- affine_xQmP Fp2
-}
-
-// A point on the projective line P^1(F_{p^2}).
-//
-// This is used to work projectively with the curve coefficients.
-type ProjectiveCurveParameters struct {
- A Fp2
- C Fp2
-}
-
-const (
- // First 2 bits identify SIDH variant third bit indicates
- // whether key is a SIKE variant (set) or SIDH (not set)
-
- // 001 - SIDH: corresponds to 2-torsion group
- KeyVariant_SIDH_A KeyVariant = 1 << 0
- // 010 - SIDH: corresponds to 3-torsion group
- KeyVariant_SIDH_B = 1 << 1
- // 110 - SIKE
- KeyVariant_SIKE = 1<<2 | KeyVariant_SIDH_B
- // Number of uint64 limbs used to store field element
- FP_WORDS = 7
-)
-
-// Used internally by this package
-// -------------------------------
-
-var (
- p = Fp{
- 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFDC1767AE2FFFFFF,
- 0x7BC65C783158AEA3, 0x6CFC5FD681C52056, 0x2341F27177344,
- }
-
- // 2*p434
- pX2 = Fp{
- 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFB82ECF5C5FFFFFF,
- 0xF78CB8F062B15D47, 0xD9F8BFAD038A40AC, 0x4683E4E2EE688,
- }
-
- // p434 + 1
- p1 = Fp{
- 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0xFDC1767AE3000000,
- 0x7BC65C783158AEA3, 0x6CFC5FD681C52056, 0x0002341F27177344,
- }
-
- // R^2=(2^448)^2 mod p
- R2 = Fp{
- 0x28E55B65DCD69B30, 0xACEC7367768798C2, 0xAB27973F8311688D, 0x175CC6AF8D6C7C0B,
- 0xABCD92BF2DDE347E, 0x69E16A61C7686D9A, 0x000025A89BCDD12A,
- }
-
- // 1/2 * R mod p
- half = Fp2{
- A: Fp{
- 0x0000000000003A16, 0x0000000000000000, 0x0000000000000000, 0x5C87FA027E000000,
- 0x6C00D27DAACFD66A, 0x74992A2A2FBBA086, 0x0000767753DE976D},
- }
-
- // 1*R mod p
- one = Fp2{
- A: Fp{
- 0x000000000000742C, 0x0000000000000000, 0x0000000000000000, 0xB90FF404FC000000,
- 0xD801A4FB559FACD4, 0xE93254545F77410C, 0x0000ECEEA7BD2EDA},
- }
-
- // 6*R mod p
- six = Fp2{
- A: Fp{
- 0x000000000002B90A, 0x0000000000000000, 0x0000000000000000, 0x5ADCCB2822000000,
- 0x187D24F39F0CAFB4, 0x9D353A4D394145A0, 0x00012559A0403298},
- }
-
- Params SidhParams
-)
-
-func init() {
- Params = SidhParams{
- // SIDH public key byte size.
- PublicKeySize: 330,
- // SIDH shared secret byte size.
- SharedSecretSize: 110,
- InitCurve: ProjectiveCurveParameters{
- A: six,
- C: one,
- },
- A: DomainParams{
- // The x-coordinate of PA
- Affine_P: Fp2{
- A: Fp{
- 0x05ADF455C5C345BF, 0x91935C5CC767AC2B, 0xAFE4E879951F0257, 0x70E792DC89FA27B1,
- 0xF797F526BB48C8CD, 0x2181DB6131AF621F, 0x00000A1C08B1ECC4,
- },
- B: Fp{
- 0x74840EB87CDA7788, 0x2971AA0ECF9F9D0B, 0xCB5732BDF41715D5, 0x8CD8E51F7AACFFAA,
- 0xA7F424730D7E419F, 0xD671EB919A179E8C, 0x0000FFA26C5A924A,
- },
- },
- // The x-coordinate of QA
- Affine_Q: Fp2{
- A: Fp{
- 0xFEC6E64588B7273B, 0xD2A626D74CBBF1C6, 0xF8F58F07A78098C7, 0xE23941F470841B03,
- 0x1B63EDA2045538DD, 0x735CFEB0FFD49215, 0x0001C4CB77542876,
- },
- B: Fp{
- 0xADB0F733C17FFDD6, 0x6AFFBD037DA0A050, 0x680EC43DB144E02F, 0x1E2E5D5FF524E374,
- 0xE2DDA115260E2995, 0xA6E4B552E2EDE508, 0x00018ECCDDF4B53E,
- },
- },
- // The x-coordinate of RA = PA-QA
- Affine_R: Fp2{
- A: Fp{
- 0x01BA4DB518CD6C7D, 0x2CB0251FE3CC0611, 0x259B0C6949A9121B, 0x60E17AC16D2F82AD,
- 0x3AA41F1CE175D92D, 0x413FBE6A9B9BC4F3, 0x00022A81D8D55643,
- },
- B: Fp{
- 0xB8ADBC70FC82E54A, 0xEF9CDDB0D5FADDED, 0x5820C734C80096A0, 0x7799994BAA96E0E4,
- 0x044961599E379AF8, 0xDB2B94FBF09F27E2, 0x0000B87FC716C0C6,
- },
- },
- // Max size of secret key for 2-torsion group, corresponds to 2^e2 - 1
- SecretBitLen: 216,
- // SecretBitLen in bytes.
- SecretByteLen: 27,
- // 2-torsion group computation strategy
- IsogenyStrategy: []uint32{
- 0x30, 0x1C, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01,
- 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x04,
- 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x0D, 0x07, 0x04, 0x02, 0x01, 0x01, 0x02,
- 0x01, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x05, 0x04,
- 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
- 0x15, 0x0C, 0x07, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
- 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x05, 0x03, 0x02, 0x01,
- 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x09, 0x05, 0x03,
- 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x04,
- 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01},
- },
- B: DomainParams{
- // The x-coordinate of PB
- Affine_P: Fp2{
- A: Fp{
- 0x6E5497556EDD48A3, 0x2A61B501546F1C05, 0xEB919446D049887D, 0x5864A4A69D450C4F,
- 0xB883F276A6490D2B, 0x22CC287022D5F5B9, 0x0001BED4772E551F,
- },
- B: Fp{
- 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
- 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
- },
- },
- // The x-coordinate of QB
- Affine_Q: Fp2{
- A: Fp{
- 0xFAE2A3F93D8B6B8E, 0x494871F51700FE1C, 0xEF1A94228413C27C, 0x498FF4A4AF60BD62,
- 0xB00AD2A708267E8A, 0xF4328294E017837F, 0x000034080181D8AE,
- },
- B: Fp{
- 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
- 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
- },
- },
- // The x-coordinate of RB = PB - QB
- Affine_R: Fp2{
- A: Fp{
- 0x283B34FAFEFDC8E4, 0x9208F44977C3E647, 0x7DEAE962816F4E9A, 0x68A2BA8AA262EC9D,
- 0x8176F112EA43F45B, 0x02106D022634F504, 0x00007E8A50F02E37,
- },
- B: Fp{
- 0xB378B7C1DA22CCB1, 0x6D089C99AD1D9230, 0xEBE15711813E2369, 0x2B35A68239D48A53,
- 0x445F6FD138407C93, 0xBEF93B29A3F6B54B, 0x000173FA910377D3,
- },
- },
- // Size of secret key for 3-torsion group, corresponds to log_2(3^e3) - 1.
- SecretBitLen: 217,
- // SecretBitLen in bytes.
- SecretByteLen: 28,
- // 3-torsion group computation strategy
- IsogenyStrategy: []uint32{
- 0x42, 0x21, 0x11, 0x09, 0x05, 0x03, 0x02, 0x01, 0x01, 0x01,
- 0x01, 0x02, 0x01, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02,
- 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x10,
- 0x08, 0x04, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04,
- 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x08, 0x04, 0x02, 0x01,
- 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01,
- 0x01, 0x20, 0x10, 0x08, 0x04, 0x03, 0x01, 0x01, 0x01, 0x01,
- 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
- 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04, 0x02,
- 0x01, 0x01, 0x02, 0x01, 0x01, 0x10, 0x08, 0x04, 0x02, 0x01,
- 0x01, 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01,
- 0x01, 0x08, 0x04, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x04,
- 0x02, 0x01, 0x01, 0x02, 0x01, 0x01},
- },
- OneFp2: one,
- HalfFp2: half,
- MsgLen: 16,
- // SIKEp434 provides 128 bit of classical security ([SIKE], 5.1)
- KemSize: 16,
- // ceil(434+7/8)
- Bytelen: 55,
- CiphertextSize: 16 + 330,
- }
-}
diff --git a/ssl/test/runner/sike/curve.go b/ssl/test/runner/sike/curve.go
deleted file mode 100644
index 8172546..0000000
--- a/ssl/test/runner/sike/curve.go
+++ /dev/null
@@ -1,422 +0,0 @@
-// Copyright (c) 2019, Cloudflare Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package sike
-
-// Interface for working with isogenies.
-type isogeny interface {
- // Given a torsion point on a curve computes isogenous curve.
- // Returns curve coefficients (A:C), so that E_(A/C) = E_(A/C)/<P>,
- // where P is a provided projective point. Sets also isogeny constants
- // that are needed for isogeny evaluation.
- GenerateCurve(*ProjectivePoint) CurveCoefficientsEquiv
- // Evaluates isogeny at caller provided point. Requires isogeny curve constants
- // to be earlier computed by GenerateCurve.
- EvaluatePoint(*ProjectivePoint) ProjectivePoint
-}
-
-// Stores isogeny 3 curve constants
-type isogeny3 struct {
- K1 Fp2
- K2 Fp2
-}
-
-// Stores isogeny 4 curve constants
-type isogeny4 struct {
- isogeny3
- K3 Fp2
-}
-
-// Constructs isogeny3 objects
-func NewIsogeny3() isogeny {
- return &isogeny3{}
-}
-
-// Constructs isogeny4 objects
-func NewIsogeny4() isogeny {
- return &isogeny4{}
-}
-
-// Helper function for RightToLeftLadder(). Returns A+2C / 4.
-func calcAplus2Over4(cparams *ProjectiveCurveParameters) (ret Fp2) {
- var tmp Fp2
-
- // 2C
- add(&tmp, &cparams.C, &cparams.C)
- // A+2C
- add(&ret, &cparams.A, &tmp)
- // 1/4C
- add(&tmp, &tmp, &tmp)
- inv(&tmp, &tmp)
- // A+2C/4C
- mul(&ret, &ret, &tmp)
- return
-}
-
-// Converts values in x.A and x.B to Montgomery domain
-// x.A = x.A * R mod p
-// x.B = x.B * R mod p
-// Performs v = v*R^2*R^(-1) mod p, for both x.A and x.B
-func toMontDomain(x *Fp2) {
- var aRR FpX2
-
- // convert to montgomery domain
- fpMul(&aRR, &x.A, &R2) // = a*R*R
- fpMontRdc(&x.A, &aRR) // = a*R mod p
- fpMul(&aRR, &x.B, &R2)
- fpMontRdc(&x.B, &aRR)
-}
-
-// Converts values in x.A and x.B from Montgomery domain
-// a = x.A mod p
-// b = x.B mod p
-//
-// After returning from the call x is not modified.
-func fromMontDomain(x *Fp2, out *Fp2) {
- var aR FpX2
-
- // convert from montgomery domain
- copy(aR[:], x.A[:])
- fpMontRdc(&out.A, &aR) // = a mod p in [0, 2p)
- fpRdcP(&out.A) // = a mod p in [0, p)
- for i := range aR {
- aR[i] = 0
- }
- copy(aR[:], x.B[:])
- fpMontRdc(&out.B, &aR)
- fpRdcP(&out.B)
-}
-
-// Computes j-invariant for a curve y2=x3+A/Cx+x with A,C in F_(p^2). Result
-// is returned in 'j'. Implementation corresponds to Algorithm 9 from SIKE.
-func Jinvariant(cparams *ProjectiveCurveParameters, j *Fp2) {
- var t0, t1 Fp2
-
- sqr(j, &cparams.A) // j = A^2
- sqr(&t1, &cparams.C) // t1 = C^2
- add(&t0, &t1, &t1) // t0 = t1 + t1
- sub(&t0, j, &t0) // t0 = j - t0
- sub(&t0, &t0, &t1) // t0 = t0 - t1
- sub(j, &t0, &t1) // t0 = t0 - t1
- sqr(&t1, &t1) // t1 = t1^2
- mul(j, j, &t1) // j = j * t1
- add(&t0, &t0, &t0) // t0 = t0 + t0
- add(&t0, &t0, &t0) // t0 = t0 + t0
- sqr(&t1, &t0) // t1 = t0^2
- mul(&t0, &t0, &t1) // t0 = t0 * t1
- add(&t0, &t0, &t0) // t0 = t0 + t0
- add(&t0, &t0, &t0) // t0 = t0 + t0
- inv(j, j) // j = 1/j
- mul(j, &t0, j) // j = t0 * j
-}
-
-// Given affine points x(P), x(Q) and x(Q-P) in a extension field F_{p^2}, function
-// recorvers projective coordinate A of a curve. This is Algorithm 10 from SIKE.
-func RecoverCoordinateA(curve *ProjectiveCurveParameters, xp, xq, xr *Fp2) {
- var t0, t1 Fp2
-
- add(&t1, xp, xq) // t1 = Xp + Xq
- mul(&t0, xp, xq) // t0 = Xp * Xq
- mul(&curve.A, xr, &t1) // A = X(q-p) * t1
- add(&curve.A, &curve.A, &t0) // A = A + t0
- mul(&t0, &t0, xr) // t0 = t0 * X(q-p)
- sub(&curve.A, &curve.A, &Params.OneFp2) // A = A - 1
- add(&t0, &t0, &t0) // t0 = t0 + t0
- add(&t1, &t1, xr) // t1 = t1 + X(q-p)
- add(&t0, &t0, &t0) // t0 = t0 + t0
- sqr(&curve.A, &curve.A) // A = A^2
- inv(&t0, &t0) // t0 = 1/t0
- mul(&curve.A, &curve.A, &t0) // A = A * t0
- sub(&curve.A, &curve.A, &t1) // A = A - t1
-}
-
-// Computes equivalence (A:C) ~ (A+2C : A-2C)
-func CalcCurveParamsEquiv3(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv {
- var coef CurveCoefficientsEquiv
- var c2 Fp2
-
- add(&c2, &cparams.C, &cparams.C)
- // A24p = A+2*C
- add(&coef.A, &cparams.A, &c2)
- // A24m = A-2*C
- sub(&coef.C, &cparams.A, &c2)
- return coef
-}
-
-// Computes equivalence (A:C) ~ (A+2C : 4C)
-func CalcCurveParamsEquiv4(cparams *ProjectiveCurveParameters) CurveCoefficientsEquiv {
- var coefEq CurveCoefficientsEquiv
-
- add(&coefEq.C, &cparams.C, &cparams.C)
- // A24p = A+2C
- add(&coefEq.A, &cparams.A, &coefEq.C)
- // C24 = 4*C
- add(&coefEq.C, &coefEq.C, &coefEq.C)
- return coefEq
-}
-
-// Recovers (A:C) curve parameters from projectively equivalent (A+2C:A-2C).
-func RecoverCurveCoefficients3(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) {
- add(&cparams.A, &coefEq.A, &coefEq.C)
- // cparams.A = 2*(A+2C+A-2C) = 4A
- add(&cparams.A, &cparams.A, &cparams.A)
- // cparams.C = (A+2C-A+2C) = 4C
- sub(&cparams.C, &coefEq.A, &coefEq.C)
- return
-}
-
-// Recovers (A:C) curve parameters from projectively equivalent (A+2C:4C).
-func RecoverCurveCoefficients4(cparams *ProjectiveCurveParameters, coefEq *CurveCoefficientsEquiv) {
- // cparams.C = (4C)*1/2=2C
- mul(&cparams.C, &coefEq.C, &Params.HalfFp2)
- // cparams.A = A+2C - 2C = A
- sub(&cparams.A, &coefEq.A, &cparams.C)
- // cparams.C = 2C * 1/2 = C
- mul(&cparams.C, &cparams.C, &Params.HalfFp2)
- return
-}
-
-// Combined coordinate doubling and differential addition. Takes projective points
-// P,Q,Q-P and (A+2C)/4C curve E coefficient. Returns 2*P and P+Q calculated on E.
-// Function is used only by RightToLeftLadder. Corresponds to Algorithm 5 of SIKE
-func xDbladd(P, Q, QmP *ProjectivePoint, a24 *Fp2) (dblP, PaQ ProjectivePoint) {
- var t0, t1, t2 Fp2
- xQmP, zQmP := &QmP.X, &QmP.Z
- xPaQ, zPaQ := &PaQ.X, &PaQ.Z
- x2P, z2P := &dblP.X, &dblP.Z
- xP, zP := &P.X, &P.Z
- xQ, zQ := &Q.X, &Q.Z
-
- add(&t0, xP, zP) // t0 = Xp+Zp
- sub(&t1, xP, zP) // t1 = Xp-Zp
- sqr(x2P, &t0) // 2P.X = t0^2
- sub(&t2, xQ, zQ) // t2 = Xq-Zq
- add(xPaQ, xQ, zQ) // Xp+q = Xq+Zq
- mul(&t0, &t0, &t2) // t0 = t0 * t2
- mul(z2P, &t1, &t1) // 2P.Z = t1 * t1
- mul(&t1, &t1, xPaQ) // t1 = t1 * Xp+q
- sub(&t2, x2P, z2P) // t2 = 2P.X - 2P.Z
- mul(x2P, x2P, z2P) // 2P.X = 2P.X * 2P.Z
- mul(xPaQ, a24, &t2) // Xp+q = A24 * t2
- sub(zPaQ, &t0, &t1) // Zp+q = t0 - t1
- add(z2P, xPaQ, z2P) // 2P.Z = Xp+q + 2P.Z
- add(xPaQ, &t0, &t1) // Xp+q = t0 + t1
- mul(z2P, z2P, &t2) // 2P.Z = 2P.Z * t2
- sqr(zPaQ, zPaQ) // Zp+q = Zp+q ^ 2
- sqr(xPaQ, xPaQ) // Xp+q = Xp+q ^ 2
- mul(zPaQ, xQmP, zPaQ) // Zp+q = Xq-p * Zp+q
- mul(xPaQ, zQmP, xPaQ) // Xp+q = Zq-p * Xp+q
- return
-}
-
-// Given the curve parameters, xP = x(P), computes xP = x([2^k]P)
-// Safe to overlap xP, x2P.
-func Pow2k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) {
- var t0, t1 Fp2
-
- x, z := &xP.X, &xP.Z
- for i := uint32(0); i < k; i++ {
- sub(&t0, x, z) // t0 = Xp - Zp
- add(&t1, x, z) // t1 = Xp + Zp
- sqr(&t0, &t0) // t0 = t0 ^ 2
- sqr(&t1, &t1) // t1 = t1 ^ 2
- mul(z, ¶ms.C, &t0) // Z2p = C24 * t0
- mul(x, z, &t1) // X2p = Z2p * t1
- sub(&t1, &t1, &t0) // t1 = t1 - t0
- mul(&t0, ¶ms.A, &t1) // t0 = A24+ * t1
- add(z, z, &t0) // Z2p = Z2p + t0
- mul(z, z, &t1) // Zp = Z2p * t1
- }
-}
-
-// Given the curve parameters, xP = x(P), and k >= 0, compute xP = x([3^k]P).
-//
-// Safe to overlap xP, xR.
-func Pow3k(xP *ProjectivePoint, params *CurveCoefficientsEquiv, k uint32) {
- var t0, t1, t2, t3, t4, t5, t6 Fp2
-
- x, z := &xP.X, &xP.Z
- for i := uint32(0); i < k; i++ {
- sub(&t0, x, z) // t0 = Xp - Zp
- sqr(&t2, &t0) // t2 = t0^2
- add(&t1, x, z) // t1 = Xp + Zp
- sqr(&t3, &t1) // t3 = t1^2
- add(&t4, &t1, &t0) // t4 = t1 + t0
- sub(&t0, &t1, &t0) // t0 = t1 - t0
- sqr(&t1, &t4) // t1 = t4^2
- sub(&t1, &t1, &t3) // t1 = t1 - t3
- sub(&t1, &t1, &t2) // t1 = t1 - t2
- mul(&t5, &t3, ¶ms.A) // t5 = t3 * A24+
- mul(&t3, &t3, &t5) // t3 = t5 * t3
- mul(&t6, &t2, ¶ms.C) // t6 = t2 * A24-
- mul(&t2, &t2, &t6) // t2 = t2 * t6
- sub(&t3, &t2, &t3) // t3 = t2 - t3
- sub(&t2, &t5, &t6) // t2 = t5 - t6
- mul(&t1, &t2, &t1) // t1 = t2 * t1
- add(&t2, &t3, &t1) // t2 = t3 + t1
- sqr(&t2, &t2) // t2 = t2^2
- mul(x, &t2, &t4) // X3p = t2 * t4
- sub(&t1, &t3, &t1) // t1 = t3 - t1
- sqr(&t1, &t1) // t1 = t1^2
- mul(z, &t1, &t0) // Z3p = t1 * t0
- }
-}
-
-// Set (y1, y2, y3) = (1/x1, 1/x2, 1/x3).
-//
-// All xi, yi must be distinct.
-func Fp2Batch3Inv(x1, x2, x3, y1, y2, y3 *Fp2) {
- var x1x2, t Fp2
-
- mul(&x1x2, x1, x2) // x1*x2
- mul(&t, &x1x2, x3) // 1/(x1*x2*x3)
- inv(&t, &t)
- mul(y1, &t, x2) // 1/x1
- mul(y1, y1, x3)
- mul(y2, &t, x1) // 1/x2
- mul(y2, y2, x3)
- mul(y3, &t, &x1x2) // 1/x3
-}
-
-// ScalarMul3Pt is a right-to-left point multiplication that given the
-// x-coordinate of P, Q and P-Q calculates the x-coordinate of R=Q+[scalar]P.
-// nbits must be smaller or equal to len(scalar).
-func ScalarMul3Pt(cparams *ProjectiveCurveParameters, P, Q, PmQ *ProjectivePoint, nbits uint, scalar []uint8) ProjectivePoint {
- var R0, R2, R1 ProjectivePoint
- aPlus2Over4 := calcAplus2Over4(cparams)
- R1 = *P
- R2 = *PmQ
- R0 = *Q
-
- // Iterate over the bits of the scalar, bottom to top
- prevBit := uint8(0)
- for i := uint(0); i < nbits; i++ {
- bit := (scalar[i>>3] >> (i & 7) & 1)
- swap := prevBit ^ bit
- prevBit = bit
- condSwap(&R1.X, &R1.Z, &R2.X, &R2.Z, swap)
- R0, R2 = xDbladd(&R0, &R2, &R1, &aPlus2Over4)
- }
- condSwap(&R1.X, &R1.Z, &R2.X, &R2.Z, prevBit)
- return R1
-}
-
-// Given a three-torsion point p = x(PB) on the curve E_(A:C), construct the
-// three-isogeny phi : E_(A:C) -> E_(A:C)/<P_3> = E_(A':C').
-//
-// Input: (XP_3: ZP_3), where P_3 has exact order 3 on E_A/C
-// Output: * Curve coordinates (A' + 2C', A' - 2C') corresponding to E_A'/C' = A_E/C/<P3>
-// * isogeny phi with constants in F_p^2
-func (phi *isogeny3) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv {
- var t0, t1, t2, t3, t4 Fp2
- var coefEq CurveCoefficientsEquiv
- var K1, K2 = &phi.K1, &phi.K2
-
- sub(K1, &p.X, &p.Z) // K1 = XP3 - ZP3
- sqr(&t0, K1) // t0 = K1^2
- add(K2, &p.X, &p.Z) // K2 = XP3 + ZP3
- sqr(&t1, K2) // t1 = K2^2
- add(&t2, &t0, &t1) // t2 = t0 + t1
- add(&t3, K1, K2) // t3 = K1 + K2
- sqr(&t3, &t3) // t3 = t3^2
- sub(&t3, &t3, &t2) // t3 = t3 - t2
- add(&t2, &t1, &t3) // t2 = t1 + t3
- add(&t3, &t3, &t0) // t3 = t3 + t0
- add(&t4, &t3, &t0) // t4 = t3 + t0
- add(&t4, &t4, &t4) // t4 = t4 + t4
- add(&t4, &t1, &t4) // t4 = t1 + t4
- mul(&coefEq.C, &t2, &t4) // A24m = t2 * t4
- add(&t4, &t1, &t2) // t4 = t1 + t2
- add(&t4, &t4, &t4) // t4 = t4 + t4
- add(&t4, &t0, &t4) // t4 = t0 + t4
- mul(&t4, &t3, &t4) // t4 = t3 * t4
- sub(&t0, &t4, &coefEq.C) // t0 = t4 - A24m
- add(&coefEq.A, &coefEq.C, &t0) // A24p = A24m + t0
- return coefEq
-}
-
-// Given a 3-isogeny phi and a point pB = x(PB), compute x(QB), the x-coordinate
-// of the image QB = phi(PB) of PB under phi : E_(A:C) -> E_(A':C').
-//
-// The output xQ = x(Q) is then a point on the curve E_(A':C'); the curve
-// parameters are returned by the GenerateCurve function used to construct phi.
-func (phi *isogeny3) EvaluatePoint(p *ProjectivePoint) ProjectivePoint {
- var t0, t1, t2 Fp2
- var q ProjectivePoint
- var K1, K2 = &phi.K1, &phi.K2
- var px, pz = &p.X, &p.Z
-
- add(&t0, px, pz) // t0 = XQ + ZQ
- sub(&t1, px, pz) // t1 = XQ - ZQ
- mul(&t0, K1, &t0) // t2 = K1 * t0
- mul(&t1, K2, &t1) // t1 = K2 * t1
- add(&t2, &t0, &t1) // t2 = t0 + t1
- sub(&t0, &t1, &t0) // t0 = t1 - t0
- sqr(&t2, &t2) // t2 = t2 ^ 2
- sqr(&t0, &t0) // t0 = t0 ^ 2
- mul(&q.X, px, &t2) // XQ'= XQ * t2
- mul(&q.Z, pz, &t0) // ZQ'= ZQ * t0
- return q
-}
-
-// Given a four-torsion point p = x(PB) on the curve E_(A:C), construct the
-// four-isogeny phi : E_(A:C) -> E_(A:C)/<P_4> = E_(A':C').
-//
-// Input: (XP_4: ZP_4), where P_4 has exact order 4 on E_A/C
-// Output: * Curve coordinates (A' + 2C', 4C') corresponding to E_A'/C' = A_E/C/<P4>
-// * isogeny phi with constants in F_p^2
-func (phi *isogeny4) GenerateCurve(p *ProjectivePoint) CurveCoefficientsEquiv {
- var coefEq CurveCoefficientsEquiv
- var xp4, zp4 = &p.X, &p.Z
- var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3
-
- sub(K2, xp4, zp4)
- add(K3, xp4, zp4)
- sqr(K1, zp4)
- add(K1, K1, K1)
- sqr(&coefEq.C, K1)
- add(K1, K1, K1)
- sqr(&coefEq.A, xp4)
- add(&coefEq.A, &coefEq.A, &coefEq.A)
- sqr(&coefEq.A, &coefEq.A)
- return coefEq
-}
-
-// Given a 4-isogeny phi and a point xP = x(P), compute x(Q), the x-coordinate
-// of the image Q = phi(P) of P under phi : E_(A:C) -> E_(A':C').
-//
-// Input: isogeny returned by GenerateCurve and point q=(Qx,Qz) from E0_A/C
-// Output: Corresponding point q from E1_A'/C', where E1 is 4-isogenous to E0
-func (phi *isogeny4) EvaluatePoint(p *ProjectivePoint) ProjectivePoint {
- var t0, t1 Fp2
- var q = *p
- var xq, zq = &q.X, &q.Z
- var K1, K2, K3 = &phi.K1, &phi.K2, &phi.K3
-
- add(&t0, xq, zq)
- sub(&t1, xq, zq)
- mul(xq, &t0, K2)
- mul(zq, &t1, K3)
- mul(&t0, &t0, &t1)
- mul(&t0, &t0, K1)
- add(&t1, xq, zq)
- sub(zq, xq, zq)
- sqr(&t1, &t1)
- sqr(zq, zq)
- add(xq, &t0, &t1)
- sub(&t0, zq, &t0)
- mul(xq, xq, &t1)
- mul(zq, zq, &t0)
- return q
-}
diff --git a/ssl/test/runner/sike/sike.go b/ssl/test/runner/sike/sike.go
deleted file mode 100644
index dcd6cfc..0000000
--- a/ssl/test/runner/sike/sike.go
+++ /dev/null
@@ -1,683 +0,0 @@
-// Copyright (c) 2019, Cloudflare Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package sike
-
-import (
- "crypto/sha256"
- "crypto/subtle"
- "errors"
- "io"
-)
-
-// Zeroize Fp2
-func zeroize(fp *Fp2) {
- // Zeroizing in 2 separated loops tells compiler to
- // use fast runtime.memclr()
- for i := range fp.A {
- fp.A[i] = 0
- }
- for i := range fp.B {
- fp.B[i] = 0
- }
-}
-
-// Convert the input to wire format.
-//
-// The output byte slice must be at least 2*bytelen(p) bytes long.
-func convFp2ToBytes(output []byte, fp2 *Fp2) {
- if len(output) < 2*Params.Bytelen {
- panic("output byte slice too short")
- }
- var a Fp2
- fromMontDomain(fp2, &a)
-
- // convert to bytes in little endian form
- for i := 0; i < Params.Bytelen; i++ {
- // set i = j*8 + k
- tmp := i / 8
- k := uint64(i % 8)
- output[i] = byte(a.A[tmp] >> (8 * k))
- output[i+Params.Bytelen] = byte(a.B[tmp] >> (8 * k))
- }
-}
-
-// Read 2*bytelen(p) bytes into the given ExtensionFieldElement.
-//
-// It is an error to call this function if the input byte slice is less than 2*bytelen(p) bytes long.
-func convBytesToFp2(fp2 *Fp2, input []byte) {
- if len(input) < 2*Params.Bytelen {
- panic("input byte slice too short")
- }
-
- for i := 0; i < Params.Bytelen; i++ {
- j := i / 8
- k := uint64(i % 8)
- fp2.A[j] |= uint64(input[i]) << (8 * k)
- fp2.B[j] |= uint64(input[i+Params.Bytelen]) << (8 * k)
- }
- toMontDomain(fp2)
-}
-
-// -----------------------------------------------------------------------------
-// Functions for traversing isogeny trees acoording to strategy. Key type 'A' is
-//
-
-// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
-// for public key generation.
-func traverseTreePublicKeyA(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
- var points = make([]ProjectivePoint, 0, 8)
- var indices = make([]int, 0, 8)
- var i, sidx int
-
- cparam := CalcCurveParamsEquiv4(curve)
- phi := NewIsogeny4()
- strat := pub.params.A.IsogenyStrategy
- stratSz := len(strat)
-
- for j := 1; j <= stratSz; j++ {
- for i <= stratSz-j {
- points = append(points, *xR)
- indices = append(indices, i)
-
- k := strat[sidx]
- sidx++
- Pow2k(xR, &cparam, 2*k)
- i += int(k)
- }
-
- cparam = phi.GenerateCurve(xR)
- for k := 0; k < len(points); k++ {
- points[k] = phi.EvaluatePoint(&points[k])
- }
-
- *phiP = phi.EvaluatePoint(phiP)
- *phiQ = phi.EvaluatePoint(phiQ)
- *phiR = phi.EvaluatePoint(phiR)
-
- // pop xR from points
- *xR, points = points[len(points)-1], points[:len(points)-1]
- i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
- }
-}
-
-// Traverses isogeny tree in order to compute xR needed
-// for public key generation.
-func traverseTreeSharedKeyA(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
- var points = make([]ProjectivePoint, 0, 8)
- var indices = make([]int, 0, 8)
- var i, sidx int
-
- cparam := CalcCurveParamsEquiv4(curve)
- phi := NewIsogeny4()
- strat := pub.params.A.IsogenyStrategy
- stratSz := len(strat)
-
- for j := 1; j <= stratSz; j++ {
- for i <= stratSz-j {
- points = append(points, *xR)
- indices = append(indices, i)
-
- k := strat[sidx]
- sidx++
- Pow2k(xR, &cparam, 2*k)
- i += int(k)
- }
-
- cparam = phi.GenerateCurve(xR)
- for k := 0; k < len(points); k++ {
- points[k] = phi.EvaluatePoint(&points[k])
- }
-
- // pop xR from points
- *xR, points = points[len(points)-1], points[:len(points)-1]
- i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
- }
-}
-
-// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
-// for public key generation.
-func traverseTreePublicKeyB(curve *ProjectiveCurveParameters, xR, phiP, phiQ, phiR *ProjectivePoint, pub *PublicKey) {
- var points = make([]ProjectivePoint, 0, 8)
- var indices = make([]int, 0, 8)
- var i, sidx int
-
- cparam := CalcCurveParamsEquiv3(curve)
- phi := NewIsogeny3()
- strat := pub.params.B.IsogenyStrategy
- stratSz := len(strat)
-
- for j := 1; j <= stratSz; j++ {
- for i <= stratSz-j {
- points = append(points, *xR)
- indices = append(indices, i)
-
- k := strat[sidx]
- sidx++
- Pow3k(xR, &cparam, k)
- i += int(k)
- }
-
- cparam = phi.GenerateCurve(xR)
- for k := 0; k < len(points); k++ {
- points[k] = phi.EvaluatePoint(&points[k])
- }
-
- *phiP = phi.EvaluatePoint(phiP)
- *phiQ = phi.EvaluatePoint(phiQ)
- *phiR = phi.EvaluatePoint(phiR)
-
- // pop xR from points
- *xR, points = points[len(points)-1], points[:len(points)-1]
- i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
- }
-}
-
-// Traverses isogeny tree in order to compute xR, xP, xQ and xQmP needed
-// for public key generation.
-func traverseTreeSharedKeyB(curve *ProjectiveCurveParameters, xR *ProjectivePoint, pub *PublicKey) {
- var points = make([]ProjectivePoint, 0, 8)
- var indices = make([]int, 0, 8)
- var i, sidx int
-
- cparam := CalcCurveParamsEquiv3(curve)
- phi := NewIsogeny3()
- strat := pub.params.B.IsogenyStrategy
- stratSz := len(strat)
-
- for j := 1; j <= stratSz; j++ {
- for i <= stratSz-j {
- points = append(points, *xR)
- indices = append(indices, i)
-
- k := strat[sidx]
- sidx++
- Pow3k(xR, &cparam, k)
- i += int(k)
- }
-
- cparam = phi.GenerateCurve(xR)
- for k := 0; k < len(points); k++ {
- points[k] = phi.EvaluatePoint(&points[k])
- }
-
- // pop xR from points
- *xR, points = points[len(points)-1], points[:len(points)-1]
- i, indices = int(indices[len(indices)-1]), indices[:len(indices)-1]
- }
-}
-
-// Generate a public key in the 2-torsion group
-func publicKeyGenA(prv *PrivateKey) (pub *PublicKey) {
- var xPA, xQA, xRA ProjectivePoint
- var xPB, xQB, xRB, xK ProjectivePoint
- var invZP, invZQ, invZR Fp2
-
- pub = NewPublicKey(KeyVariant_SIDH_A)
- var phi = NewIsogeny4()
-
- // Load points for A
- xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
- xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
- xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
-
- // Load points for B
- xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
- xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
- xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
-
- // Find isogeny kernel
- xK = ScalarMul3Pt(&pub.params.InitCurve, &xPA, &xQA, &xRA, prv.params.A.SecretBitLen, prv.Scalar)
- traverseTreePublicKeyA(&pub.params.InitCurve, &xK, &xPB, &xQB, &xRB, pub)
-
- // Secret isogeny
- phi.GenerateCurve(&xK)
- xPA = phi.EvaluatePoint(&xPB)
- xQA = phi.EvaluatePoint(&xQB)
- xRA = phi.EvaluatePoint(&xRB)
- Fp2Batch3Inv(&xPA.Z, &xQA.Z, &xRA.Z, &invZP, &invZQ, &invZR)
-
- mul(&pub.affine_xP, &xPA.X, &invZP)
- mul(&pub.affine_xQ, &xQA.X, &invZQ)
- mul(&pub.affine_xQmP, &xRA.X, &invZR)
- return
-}
-
-// Generate a public key in the 3-torsion group
-func publicKeyGenB(prv *PrivateKey) (pub *PublicKey) {
- var xPB, xQB, xRB, xK ProjectivePoint
- var xPA, xQA, xRA ProjectivePoint
- var invZP, invZQ, invZR Fp2
-
- pub = NewPublicKey(prv.keyVariant)
- var phi = NewIsogeny3()
-
- // Load points for B
- xRB = ProjectivePoint{X: prv.params.B.Affine_R, Z: prv.params.OneFp2}
- xQB = ProjectivePoint{X: prv.params.B.Affine_Q, Z: prv.params.OneFp2}
- xPB = ProjectivePoint{X: prv.params.B.Affine_P, Z: prv.params.OneFp2}
-
- // Load points for A
- xPA = ProjectivePoint{X: prv.params.A.Affine_P, Z: prv.params.OneFp2}
- xQA = ProjectivePoint{X: prv.params.A.Affine_Q, Z: prv.params.OneFp2}
- xRA = ProjectivePoint{X: prv.params.A.Affine_R, Z: prv.params.OneFp2}
-
- xK = ScalarMul3Pt(&pub.params.InitCurve, &xPB, &xQB, &xRB, prv.params.B.SecretBitLen, prv.Scalar)
- traverseTreePublicKeyB(&pub.params.InitCurve, &xK, &xPA, &xQA, &xRA, pub)
-
- phi.GenerateCurve(&xK)
- xPB = phi.EvaluatePoint(&xPA)
- xQB = phi.EvaluatePoint(&xQA)
- xRB = phi.EvaluatePoint(&xRA)
- Fp2Batch3Inv(&xPB.Z, &xQB.Z, &xRB.Z, &invZP, &invZQ, &invZR)
-
- mul(&pub.affine_xP, &xPB.X, &invZP)
- mul(&pub.affine_xQ, &xQB.X, &invZQ)
- mul(&pub.affine_xQmP, &xRB.X, &invZR)
- return
-}
-
-// -----------------------------------------------------------------------------
-// Key agreement functions
-//
-
-// Establishing shared keys in in 2-torsion group
-func deriveSecretA(prv *PrivateKey, pub *PublicKey) []byte {
- var sharedSecret = make([]byte, pub.params.SharedSecretSize)
- var xP, xQ, xQmP ProjectivePoint
- var xK ProjectivePoint
- var cparam ProjectiveCurveParameters
- var phi = NewIsogeny4()
- var jInv Fp2
-
- // Recover curve coefficients
- RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
- // C=1
- cparam.C = Params.OneFp2
-
- // Find kernel of the morphism
- xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
- xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
- xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
- xK = ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.A.SecretBitLen, prv.Scalar)
-
- // Traverse isogeny tree
- traverseTreeSharedKeyA(&cparam, &xK, pub)
-
- // Calculate j-invariant on isogeneus curve
- c := phi.GenerateCurve(&xK)
- RecoverCurveCoefficients4(&cparam, &c)
- Jinvariant(&cparam, &jInv)
- convFp2ToBytes(sharedSecret, &jInv)
- return sharedSecret
-}
-
-// Establishing shared keys in in 3-torsion group
-func deriveSecretB(prv *PrivateKey, pub *PublicKey) []byte {
- var sharedSecret = make([]byte, pub.params.SharedSecretSize)
- var xP, xQ, xQmP ProjectivePoint
- var xK ProjectivePoint
- var cparam ProjectiveCurveParameters
- var phi = NewIsogeny3()
- var jInv Fp2
-
- // Recover curve A coefficient
- RecoverCoordinateA(&cparam, &pub.affine_xP, &pub.affine_xQ, &pub.affine_xQmP)
- // C=1
- cparam.C = Params.OneFp2
-
- // Find kernel of the morphism
- xP = ProjectivePoint{X: pub.affine_xP, Z: pub.params.OneFp2}
- xQ = ProjectivePoint{X: pub.affine_xQ, Z: pub.params.OneFp2}
- xQmP = ProjectivePoint{X: pub.affine_xQmP, Z: pub.params.OneFp2}
- xK = ScalarMul3Pt(&cparam, &xP, &xQ, &xQmP, pub.params.B.SecretBitLen, prv.Scalar)
-
- // Traverse isogeny tree
- traverseTreeSharedKeyB(&cparam, &xK, pub)
-
- // Calculate j-invariant on isogeneus curve
- c := phi.GenerateCurve(&xK)
- RecoverCurveCoefficients3(&cparam, &c)
- Jinvariant(&cparam, &jInv)
- convFp2ToBytes(sharedSecret, &jInv)
- return sharedSecret
-}
-
-func encrypt(skA *PrivateKey, pkA, pkB *PublicKey, ptext []byte) ([]byte, error) {
- if pkB.keyVariant != KeyVariant_SIKE {
- return nil, errors.New("wrong key type")
- }
-
- j, err := DeriveSecret(skA, pkB)
- if err != nil {
- return nil, err
- }
-
- if len(ptext) != pkA.params.KemSize {
- panic("Implementation error")
- }
-
- digest := sha256.Sum256(j)
- // Uses truncated digest (first 16-bytes)
- for i, _ := range ptext {
- digest[i] ^= ptext[i]
- }
-
- ret := make([]byte, pkA.Size()+len(ptext))
- copy(ret, pkA.Export())
- copy(ret[pkA.Size():], digest[:pkA.params.KemSize])
- return ret, nil
-}
-
-// NewPrivateKey initializes private key.
-// Usage of this function guarantees that the object is correctly initialized.
-func NewPrivateKey(v KeyVariant) *PrivateKey {
- prv := &PrivateKey{key: key{params: &Params, keyVariant: v}}
- if (v & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
- prv.Scalar = make([]byte, prv.params.A.SecretByteLen)
- } else {
- prv.Scalar = make([]byte, prv.params.B.SecretByteLen)
- }
- if v == KeyVariant_SIKE {
- prv.S = make([]byte, prv.params.MsgLen)
- }
- return prv
-}
-
-// NewPublicKey initializes public key.
-// Usage of this function guarantees that the object is correctly initialized.
-func NewPublicKey(v KeyVariant) *PublicKey {
- return &PublicKey{key: key{params: &Params, keyVariant: v}}
-}
-
-// Import clears content of the public key currently stored in the structure
-// and imports key stored in the byte string. Returns error in case byte string
-// size is wrong. Doesn't perform any validation.
-func (pub *PublicKey) Import(input []byte) error {
- if len(input) != pub.Size() {
- return errors.New("sidh: input to short")
- }
- ssSz := pub.params.SharedSecretSize
- convBytesToFp2(&pub.affine_xP, input[0:ssSz])
- convBytesToFp2(&pub.affine_xQ, input[ssSz:2*ssSz])
- convBytesToFp2(&pub.affine_xQmP, input[2*ssSz:3*ssSz])
- return nil
-}
-
-// Exports currently stored key. In case structure hasn't been filled with key data
-// returned byte string is filled with zeros.
-func (pub *PublicKey) Export() []byte {
- output := make([]byte, pub.params.PublicKeySize)
- ssSz := pub.params.SharedSecretSize
- convFp2ToBytes(output[0:ssSz], &pub.affine_xP)
- convFp2ToBytes(output[ssSz:2*ssSz], &pub.affine_xQ)
- convFp2ToBytes(output[2*ssSz:3*ssSz], &pub.affine_xQmP)
- return output
-}
-
-// Size returns size of the public key in bytes
-func (pub *PublicKey) Size() int {
- return pub.params.PublicKeySize
-}
-
-// Exports currently stored key. In case structure hasn't been filled with key data
-// returned byte string is filled with zeros.
-func (prv *PrivateKey) Export() []byte {
- ret := make([]byte, len(prv.Scalar)+len(prv.S))
- copy(ret, prv.S)
- copy(ret[len(prv.S):], prv.Scalar)
- return ret
-}
-
-// Size returns size of the private key in bytes
-func (prv *PrivateKey) Size() int {
- tmp := len(prv.Scalar)
- if prv.keyVariant == KeyVariant_SIKE {
- tmp += int(prv.params.MsgLen)
- }
- return tmp
-}
-
-// Import clears content of the private key currently stored in the structure
-// and imports key from octet string. In case of SIKE, the random value 'S'
-// must be prepended to the value of actual private key (see SIKE spec for details).
-// Function doesn't import public key value to PrivateKey object.
-func (prv *PrivateKey) Import(input []byte) error {
- if len(input) != prv.Size() {
- return errors.New("sidh: input to short")
- }
- copy(prv.S, input[:len(prv.S)])
- copy(prv.Scalar, input[len(prv.S):])
- return nil
-}
-
-// Generates random private key for SIDH or SIKE. Generated value is
-// formed as little-endian integer from key-space <2^(e2-1)..2^e2 - 1>
-// for KeyVariant_A or <2^(s-1)..2^s - 1>, where s = floor(log_2(3^e3)),
-// for KeyVariant_B.
-//
-// Returns error in case user provided RNG fails.
-func (prv *PrivateKey) Generate(rand io.Reader) error {
- var err error
- var dp *DomainParams
-
- if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
- dp = &prv.params.A
- } else {
- dp = &prv.params.B
- }
-
- if prv.keyVariant == KeyVariant_SIKE {
- _, err = io.ReadFull(rand, prv.S)
- }
-
- // Private key generation takes advantage of the fact that keyspace for secret
- // key is (0, 2^x - 1), for some possitivite value of 'x' (see SIKE, 1.3.8).
- // It means that all bytes in the secret key, but the last one, can take any
- // value between <0x00,0xFF>. Similarily for the last byte, but generation
- // needs to chop off some bits, to make sure generated value is an element of
- // a key-space.
- _, err = io.ReadFull(rand, prv.Scalar)
- if err != nil {
- return err
- }
- prv.Scalar[len(prv.Scalar)-1] &= (1 << (dp.SecretBitLen % 8)) - 1
- // Make sure scalar is SecretBitLen long. SIKE spec says that key
- // space starts from 0, but I'm not confortable with having low
- // value scalars used for private keys. It is still secrure as per
- // table 5.1 in [SIKE].
- prv.Scalar[len(prv.Scalar)-1] |= 1 << ((dp.SecretBitLen % 8) - 1)
- return err
-}
-
-// Generates public key.
-//
-// Constant time.
-func (prv *PrivateKey) GeneratePublicKey() *PublicKey {
- if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
- return publicKeyGenA(prv)
- }
- return publicKeyGenB(prv)
-}
-
-// Computes a shared secret which is a j-invariant. Function requires that pub has
-// different KeyVariant than prv. Length of returned output is 2*ceil(log_2 P)/8),
-// where P is a prime defining finite field.
-//
-// It's important to notice that each keypair must not be used more than once
-// to calculate shared secret.
-//
-// Function may return error. This happens only in case provided input is invalid.
-// Constant time for properly initialized private and public key.
-func DeriveSecret(prv *PrivateKey, pub *PublicKey) ([]byte, error) {
-
- if (pub == nil) || (prv == nil) {
- return nil, errors.New("sidh: invalid arguments")
- }
-
- if (pub.keyVariant == prv.keyVariant) || (pub.params.Id != prv.params.Id) {
- return nil, errors.New("sidh: public and private are incompatbile")
- }
-
- if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
- return deriveSecretA(prv, pub), nil
- } else {
- return deriveSecretB(prv, pub), nil
- }
-}
-
-// Uses SIKE public key to encrypt plaintext. Requires cryptographically secure PRNG
-// Returns ciphertext in case encryption succeeds. Returns error in case PRNG fails
-// or wrongly formatted input was provided.
-func Encrypt(rng io.Reader, pub *PublicKey, ptext []byte) ([]byte, error) {
- var ptextLen = len(ptext)
- // c1 must be security level + 64 bits (see [SIKE] 1.4 and 4.3.3)
- if ptextLen != pub.params.KemSize {
- return nil, errors.New("Unsupported message length")
- }
-
- skA := NewPrivateKey(KeyVariant_SIDH_A)
- err := skA.Generate(rng)
- if err != nil {
- return nil, err
- }
-
- pkA := skA.GeneratePublicKey()
- return encrypt(skA, pkA, pub, ptext)
-}
-
-// Uses SIKE private key to decrypt ciphertext. Returns plaintext in case
-// decryption succeeds or error in case unexptected input was provided.
-// Constant time
-func Decrypt(prv *PrivateKey, ctext []byte) ([]byte, error) {
- var c1_len int
- n := make([]byte, prv.params.KemSize)
- pk_len := prv.params.PublicKeySize
-
- if prv.keyVariant != KeyVariant_SIKE {
- return nil, errors.New("wrong key type")
- }
-
- // ctext is a concatenation of (pubkey_A || c1=ciphertext)
- // it must be security level + 64 bits (see [SIKE] 1.4 and 4.3.3)
- c1_len = len(ctext) - pk_len
- if c1_len != int(prv.params.KemSize) {
- return nil, errors.New("wrong size of cipher text")
- }
-
- c0 := NewPublicKey(KeyVariant_SIDH_A)
- err := c0.Import(ctext[:pk_len])
- if err != nil {
- return nil, err
- }
- j, err := DeriveSecret(prv, c0)
- if err != nil {
- return nil, err
- }
-
- digest := sha256.Sum256(j)
- copy(n, digest[:])
-
- for i, _ := range n {
- n[i] ^= ctext[pk_len+i]
- }
- return n[:c1_len], nil
-}
-
-// Encapsulation receives the public key and generates SIKE ciphertext and shared secret.
-// The generated ciphertext is used for authentication.
-// The rng must be cryptographically secure PRNG.
-// Error is returned in case PRNG fails or wrongly formatted input was provided.
-func Encapsulate(rng io.Reader, pub *PublicKey) (ctext []byte, secret []byte, err error) {
- // Buffer for random, secret message
- ptext := make([]byte, pub.params.MsgLen)
- // SHA256 hash context object
- d := sha256.New()
-
- // Generate ephemeral value
- _, err = io.ReadFull(rng, ptext)
- if err != nil {
- return nil, nil, err
- }
-
- // Implementation uses first 28-bytes of secret
- d.Write(ptext)
- d.Write(pub.Export())
- digest := d.Sum(nil)
- // r = G(ptext||pub)
- r := digest[:pub.params.A.SecretByteLen]
-
- // (c0 || c1) = Enc(pkA, ptext; r)
- skA := NewPrivateKey(KeyVariant_SIDH_A)
- err = skA.Import(r)
- if err != nil {
- return nil, nil, err
- }
-
- pkA := skA.GeneratePublicKey()
- ctext, err = encrypt(skA, pkA, pub, ptext)
- if err != nil {
- return nil, nil, err
- }
-
- // K = H(ptext||(c0||c1))
- d.Reset()
- d.Write(ptext)
- d.Write(ctext)
- digest = d.Sum(digest[:0])
- return ctext, digest[:pub.params.KemSize], nil
-}
-
-// Decapsulate given the keypair and ciphertext as inputs, Decapsulate outputs a shared
-// secret if plaintext verifies correctly, otherwise function outputs random value.
-// Decapsulation may fail in case input is wrongly formatted.
-// Constant time for properly initialized input.
-func Decapsulate(prv *PrivateKey, pub *PublicKey, ctext []byte) ([]byte, error) {
- var skA = NewPrivateKey(KeyVariant_SIDH_A)
- // SHA256 hash context object
- d := sha256.New()
-
- m, err := Decrypt(prv, ctext)
- if err != nil {
- return nil, err
- }
-
- // r' = G(m'||pub)
- d.Write(m)
- d.Write(pub.Export())
- digest := d.Sum(nil)
- // Never fails
- skA.Import(digest[:pub.params.A.SecretByteLen])
-
- // Never fails
- pkA := skA.GeneratePublicKey()
- c0 := pkA.Export()
-
- d.Reset()
- if subtle.ConstantTimeCompare(c0, ctext[:len(c0)]) == 1 {
- d.Write(m)
- } else {
- // S is chosen at random when generating a key and is unknown to the other party. It
- // may seem weird, but it's correct. It is important that S is unpredictable
- // to other party. Without this check, it is possible to recover a secret, by
- // providing series of invalid ciphertexts. It is also important that in case
- //
- // See more details in "On the security of supersingular isogeny cryptosystems"
- // (S. Galbraith, et al., 2016, ePrint #859).
- d.Write(prv.S)
- }
- d.Write(ctext)
- digest = d.Sum(digest[:0])
- return digest[:pub.params.KemSize], nil
-}
diff --git a/ssl/test/runner/sike/sike_test.go b/ssl/test/runner/sike/sike_test.go
deleted file mode 100644
index 2e146bc..0000000
--- a/ssl/test/runner/sike/sike_test.go
+++ /dev/null
@@ -1,698 +0,0 @@
-// Copyright (c) 2019, Cloudflare Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package sike
-
-import (
- "bufio"
- "bytes"
- "crypto/rand"
- "encoding/hex"
- "math/big"
- "strings"
- "testing"
-)
-
-var tdata = struct {
- name string
- PrB_sidh string
- PkB_sidh string
- PrA_sidh string
- PkA_sidh string
- PkB_sike string
- PrB_sike string
-}{
- name: "P-434",
- PrA_sidh: "3A727E04EA9B7E2A766A6F846489E7E7B915263BCEED308BB10FC9",
- PkA_sidh: "9E668D1E6750ED4B91EE052C32839CA9DD2E56D52BC24DECC950AA" +
- "AD24CEED3F9049C77FE80F0B9B01E7F8DAD7833EEC2286544D6380" +
- "009C379CDD3E7517CEF5E20EB01F8231D52FC30DC61D2F63FB357F" +
- "85DC6396E8A95DB9740BD3A972C8DB7901B31F074CD3E45345CA78" +
- "F900817130E688A29A7CF0073B5C00FF2C65FBE776918EF9BD8E75" +
- "B29EF7FAB791969B60B0C5B37A8992EDEF95FA7BAC40A95DAFE02E" +
- "237301FEE9A7A43FD0B73477E8035DD12B73FAFEF18D39904DDE36" +
- "53A754F36BE1888F6607C6A7951349A414352CF31A29F2C40302DB" +
- "406C48018C905EB9DC46AFBF42A9187A9BB9E51B587622A2862DC7" +
- "D5CC598BF38ED6320FB51D8697AD3D7A72ABCC32A393F0133DA8DF" +
- "5E253D9E00B760B2DF342FCE974DCFE946CFE4727783531882800F" +
- "9E5DD594D6D5A6275EEFEF9713ED838F4A06BB34D7B8D46E0B385A" +
- "AEA1C7963601",
- PrB_sidh: "E37BFE55B43B32448F375903D8D226EC94ADBFEA1D2B3536EB987001",
- PkB_sidh: "C9F73E4497AAA3FDF9EB688135866A8A83934BA10E273B8CC3808C" +
- "F0C1F5FAB3E9BB295885881B73DEBC875670C0F51C4BB40DF5FEDE" +
- "01B8AF32D1BF10508B8C17B2734EB93B2B7F5D84A4A0F2F816E9E2" +
- "C32AC253C0B6025B124D05A87A9E2A8567930F44BAA14219B941B6" +
- "B400B4AED1D796DA12A5A9F0B8F3F5EE9DD43F64CB24A3B1719DF2" +
- "78ADF56B5F3395187829DA2319DEABF6BBD6EDA244DE2B62CC5AC2" +
- "50C1009DD1CD4712B0B37406612AD002B5E51A62B51AC9C0374D14" +
- "3ABBBD58275FAFC4A5E959C54838C2D6D9FB43B7B2609061267B6A" +
- "2E6C6D01D295C4223E0D3D7A4CDCFB28A7818A737935279751A6DD" +
- "8290FD498D1F6AD5F4FFF6BDFA536713F509DCE8047252F1E7D0DD" +
- "9FCC414C0070B5DCCE3665A21A032D7FBE749181032183AFAD240B" +
- "7E671E87FBBEC3A8CA4C11AA7A9A23AC69AE2ACF54B664DECD2775" +
- "3D63508F1B02",
- PrB_sike: "4B622DE1350119C45A9F2E2EF3DC5DF56A27FCDFCDDAF58CD69B90" +
- "3752D68C200934E160B234E49EDE247601",
- PkB_sike: "1BD0A2E81307B6F96461317DDF535ACC0E59C742627BAE60D27605" +
- "E10FAF722D22A73E184CB572A12E79DCD58C6B54FB01442114CBE9" +
- "010B6CAEC25D04C16C5E42540C1524C545B8C67614ED4183C9FA5B" +
- "D0BE45A7F89FBC770EE8E7E5E391C7EE6F35F74C29E6D9E35B1663" +
- "DA01E48E9DEB2347512D366FDE505161677055E3EF23054D276E81" +
- "7E2C57025DA1C10D2461F68617F2D11256EEE4E2D7DBDF6C8E34F3" +
- "A0FD00C625428CB41857002159DAB94267ABE42D630C6AAA91AF83" +
- "7C7A6740754EA6634C45454C51B0BB4D44C3CCCCE4B32C00901CF6" +
- "9C008D013348379B2F9837F428A01B6173584691F2A6F3A3C4CF48" +
- "7D20D261B36C8CDB1BC158E2A5162A9DA4F7A97AA0879B9897E2B6" +
- "891B672201F9AEFBF799C27B2587120AC586A511360926FB7DA8EB" +
- "F5CB5272F396AE06608422BE9792E2CE9BEF21BF55B7EFF8DC7EC8" +
- "C99910D3F800",
-}
-
-/* -------------------------------------------------------------------------
- Helpers
- -------------------------------------------------------------------------*/
-// Fail if err !=nil. Display msg as an error message
-func checkErr(t testing.TB, err error, msg string) {
- t.Helper()
- if err != nil {
- t.Error(msg)
- }
-}
-
-// Utility used for running same test with all registered prime fields
-type MultiIdTestingFunc func(testing.TB)
-
-// Converts string to private key
-func convToPrv(s string, v KeyVariant) *PrivateKey {
- key := NewPrivateKey(v)
- hex, e := hex.DecodeString(s)
- if e != nil {
- panic("non-hex number provided")
- }
- e = key.Import(hex)
- if e != nil {
- panic("Can't import private key")
- }
- return key
-}
-
-// Converts string to public key
-func convToPub(s string, v KeyVariant) *PublicKey {
- key := NewPublicKey(v)
- hex, e := hex.DecodeString(s)
- if e != nil {
- panic("non-hex number provided")
- }
- e = key.Import(hex)
- if e != nil {
- panic("Can't import public key")
- }
- return key
-}
-
-/* -------------------------------------------------------------------------
- Unit tests
- -------------------------------------------------------------------------*/
-func TestKeygen(t *testing.T) {
- alicePrivate := convToPrv(tdata.PrA_sidh, KeyVariant_SIDH_A)
- bobPrivate := convToPrv(tdata.PrB_sidh, KeyVariant_SIDH_B)
- expPubA := convToPub(tdata.PkA_sidh, KeyVariant_SIDH_A)
- expPubB := convToPub(tdata.PkB_sidh, KeyVariant_SIDH_B)
-
- pubA := alicePrivate.GeneratePublicKey()
- pubB := bobPrivate.GeneratePublicKey()
-
- if !bytes.Equal(pubA.Export(), expPubA.Export()) {
- t.Fatalf("unexpected value of public key A")
- }
- if !bytes.Equal(pubB.Export(), expPubB.Export()) {
- t.Fatalf("unexpected value of public key B")
- }
-}
-
-func TestImportExport(t *testing.T) {
- var err error
- a := NewPublicKey(KeyVariant_SIDH_A)
- b := NewPublicKey(KeyVariant_SIDH_B)
-
- // Import keys
- a_hex, err := hex.DecodeString(tdata.PkA_sidh)
- checkErr(t, err, "invalid hex-number provided")
-
- err = a.Import(a_hex)
- checkErr(t, err, "import failed")
-
- b_hex, err := hex.DecodeString(tdata.PkB_sike)
- checkErr(t, err, "invalid hex-number provided")
-
- err = b.Import(b_hex)
- checkErr(t, err, "import failed")
-
- // Export and check if same
- if !bytes.Equal(b.Export(), b_hex) || !bytes.Equal(a.Export(), a_hex) {
- t.Fatalf("export/import failed")
- }
-
- if (len(b.Export()) != b.Size()) || (len(a.Export()) != a.Size()) {
- t.Fatalf("wrong size of exported keys")
- }
-}
-
-func testPrivateKeyBelowMax(t testing.TB) {
- for variant, keySz := range map[KeyVariant]*DomainParams{
- KeyVariant_SIDH_A: &Params.A,
- KeyVariant_SIDH_B: &Params.B} {
-
- func(v KeyVariant, dp *DomainParams) {
- var blen = int(dp.SecretByteLen)
- var prv = NewPrivateKey(v)
-
- // Calculate either (2^e2 - 1) or (2^s - 1); where s=ceil(log_2(3^e3)))
- maxSecertVal := big.NewInt(int64(dp.SecretBitLen))
- maxSecertVal.Exp(big.NewInt(int64(2)), maxSecertVal, nil)
- maxSecertVal.Sub(maxSecertVal, big.NewInt(1))
-
- // Do same test 1000 times
- for i := 0; i < 1000; i++ {
- err := prv.Generate(rand.Reader)
- checkErr(t, err, "Private key generation")
-
- // Convert to big-endian, as that's what expected by (*Int)SetBytes()
- secretBytes := prv.Export()
- for i := 0; i < int(blen/2); i++ {
- tmp := secretBytes[i] ^ secretBytes[blen-i-1]
- secretBytes[i] = tmp ^ secretBytes[i]
- secretBytes[blen-i-1] = tmp ^ secretBytes[blen-i-1]
- }
- prvBig := new(big.Int).SetBytes(secretBytes)
- // Check if generated key is bigger than acceptable
- if prvBig.Cmp(maxSecertVal) == 1 {
- t.Error("Generated private key is wrong")
- }
- }
- }(variant, keySz)
- }
-}
-
-func testKeyAgreement(t *testing.T, pkA, prA, pkB, prB string) {
- var e error
-
- // KeyPairs
- alicePublic := convToPub(pkA, KeyVariant_SIDH_A)
- bobPublic := convToPub(pkB, KeyVariant_SIDH_B)
- alicePrivate := convToPrv(prA, KeyVariant_SIDH_A)
- bobPrivate := convToPrv(prB, KeyVariant_SIDH_B)
-
- // Do actual test
- s1, e := DeriveSecret(bobPrivate, alicePublic)
- checkErr(t, e, "derivation s1")
- s2, e := DeriveSecret(alicePrivate, bobPublic)
- checkErr(t, e, "derivation s1")
-
- if !bytes.Equal(s1[:], s2[:]) {
- t.Fatalf("two shared keys: %d, %d do not match", s1, s2)
- }
-
- // Negative case
- dec, e := hex.DecodeString(tdata.PkA_sidh)
- if e != nil {
- t.FailNow()
- }
- dec[0] = ^dec[0]
- e = alicePublic.Import(dec)
- if e != nil {
- t.FailNow()
- }
-
- s1, e = DeriveSecret(bobPrivate, alicePublic)
- checkErr(t, e, "derivation of s1 failed")
- s2, e = DeriveSecret(alicePrivate, bobPublic)
- checkErr(t, e, "derivation of s2 failed")
-
- if bytes.Equal(s1[:], s2[:]) {
- t.Fatalf("The two shared keys: %d, %d match", s1, s2)
- }
-}
-
-func TestDerivationRoundTrip(t *testing.T) {
- var err error
-
- prvA := NewPrivateKey(KeyVariant_SIDH_A)
- prvB := NewPrivateKey(KeyVariant_SIDH_B)
-
- // Generate private keys
- err = prvA.Generate(rand.Reader)
- checkErr(t, err, "key generation failed")
- err = prvB.Generate(rand.Reader)
- checkErr(t, err, "key generation failed")
-
- // Generate public keys
- pubA := prvA.GeneratePublicKey()
- pubB := prvB.GeneratePublicKey()
-
- // Derive shared secret
- s1, err := DeriveSecret(prvB, pubA)
- checkErr(t, err, "")
-
- s2, err := DeriveSecret(prvA, pubB)
- checkErr(t, err, "")
-
- if !bytes.Equal(s1[:], s2[:]) {
- t.Fatalf("Two shared keys: \n%X, \n%X do not match", s1, s2)
- }
-}
-
-// Encrypt, Decrypt, check if input/output plaintext is the same
-func testPKERoundTrip(t testing.TB, id uint8) {
- // Message to be encrypted
- var msg = make([]byte, Params.MsgLen)
- for i, _ := range msg {
- msg[i] = byte(i)
- }
-
- // Import keys
- pkB := NewPublicKey(KeyVariant_SIKE)
- skB := NewPrivateKey(KeyVariant_SIKE)
- pk_hex, err := hex.DecodeString(tdata.PkB_sike)
- if err != nil {
- t.Fatal(err)
- }
- sk_hex, err := hex.DecodeString(tdata.PrB_sike)
- if err != nil {
- t.Fatal(err)
- }
- if pkB.Import(pk_hex) != nil || skB.Import(sk_hex) != nil {
- t.Error("Import")
- }
-
- ct, err := Encrypt(rand.Reader, pkB, msg[:])
- if err != nil {
- t.Fatal(err)
- }
- pt, err := Decrypt(skB, ct)
- if err != nil {
- t.Fatal(err)
- }
- if !bytes.Equal(pt[:], msg[:]) {
- t.Errorf("Decryption failed \n got : %X\n exp : %X", pt, msg)
- }
-}
-
-// Generate key and check if can encrypt
-func TestPKEKeyGeneration(t *testing.T) {
- // Message to be encrypted
- var msg = make([]byte, Params.MsgLen)
- var err error
- for i, _ := range msg {
- msg[i] = byte(i)
- }
-
- sk := NewPrivateKey(KeyVariant_SIKE)
- err = sk.Generate(rand.Reader)
- checkErr(t, err, "PEK key generation")
- pk := sk.GeneratePublicKey()
-
- // Try to encrypt
- ct, err := Encrypt(rand.Reader, pk, msg[:])
- checkErr(t, err, "PEK encryption")
- pt, err := Decrypt(sk, ct)
- checkErr(t, err, "PEK key decryption")
-
- if !bytes.Equal(pt[:], msg[:]) {
- t.Fatalf("Decryption failed \n got : %X\n exp : %X", pt, msg)
- }
-}
-
-func TestNegativePKE(t *testing.T) {
- var msg [40]byte
- var err error
-
- // Generate key
- sk := NewPrivateKey(KeyVariant_SIKE)
- err = sk.Generate(rand.Reader)
- checkErr(t, err, "key generation")
-
- pk := sk.GeneratePublicKey()
-
- // bytelen(msg) - 1
- ct, err := Encrypt(rand.Reader, pk, msg[:Params.KemSize+8-1])
- if err == nil {
- t.Fatal("Error hasn't been returned")
- }
- if ct != nil {
- t.Fatal("Ciphertext must be nil")
- }
-
- // KemSize - 1
- pt, err := Decrypt(sk, msg[:Params.KemSize+8-1])
- if err == nil {
- t.Fatal("Error hasn't been returned")
- }
- if pt != nil {
- t.Fatal("Ciphertext must be nil")
- }
-}
-
-func testKEMRoundTrip(t *testing.T, pkB, skB []byte) {
- // Import keys
- pk := NewPublicKey(KeyVariant_SIKE)
- sk := NewPrivateKey(KeyVariant_SIKE)
- if pk.Import(pkB) != nil || sk.Import(skB) != nil {
- t.Error("Import failed")
- }
-
- ct, ss_e, err := Encapsulate(rand.Reader, pk)
- if err != nil {
- t.Error("Encapsulate failed")
- }
-
- ss_d, err := Decapsulate(sk, pk, ct)
- if err != nil {
- t.Error("Decapsulate failed")
- }
- if !bytes.Equal(ss_e, ss_d) {
- t.Error("Shared secrets from decapsulation and encapsulation differ")
- }
-}
-
-func TestKEMRoundTrip(t *testing.T) {
- pk, err := hex.DecodeString(tdata.PkB_sike)
- checkErr(t, err, "public key B not a number")
- sk, err := hex.DecodeString(tdata.PrB_sike)
- checkErr(t, err, "private key B not a number")
- testKEMRoundTrip(t, pk, sk)
-}
-
-func TestKEMKeyGeneration(t *testing.T) {
- // Generate key
- sk := NewPrivateKey(KeyVariant_SIKE)
- checkErr(t, sk.Generate(rand.Reader), "error: key generation")
- pk := sk.GeneratePublicKey()
-
- // calculated shared secret
- ct, ss_e, err := Encapsulate(rand.Reader, pk)
-
- checkErr(t, err, "encapsulation failed")
- ss_d, err := Decapsulate(sk, pk, ct)
- checkErr(t, err, "decapsulation failed")
-
- if !bytes.Equal(ss_e, ss_d) {
- t.Fatalf("KEM failed \n encapsulated: %X\n decapsulated: %X", ss_d, ss_e)
- }
-}
-
-func TestNegativeKEM(t *testing.T) {
- sk := NewPrivateKey(KeyVariant_SIKE)
- checkErr(t, sk.Generate(rand.Reader), "error: key generation")
- pk := sk.GeneratePublicKey()
-
- ct, ss_e, err := Encapsulate(rand.Reader, pk)
- checkErr(t, err, "pre-requisite for a test failed")
-
- ct[0] = ct[0] - 1
- ss_d, err := Decapsulate(sk, pk, ct)
- checkErr(t, err, "decapsulation returns error when invalid ciphertext provided")
-
- if bytes.Equal(ss_e, ss_d) {
- // no idea how this could ever happen, but it would be very bad
- t.Error("critical error")
- }
-
- // Try encapsulating with SIDH key
- pkSidh := NewPublicKey(KeyVariant_SIDH_B)
- prSidh := NewPrivateKey(KeyVariant_SIDH_B)
- _, _, err = Encapsulate(rand.Reader, pkSidh)
- if err == nil {
- t.Error("encapsulation accepts SIDH public key")
- }
- // Try decapsulating with SIDH key
- _, err = Decapsulate(prSidh, pk, ct)
- if err == nil {
- t.Error("decapsulation accepts SIDH private key key")
- }
-}
-
-// In case invalid ciphertext is provided, SIKE's decapsulation must
-// return same (but unpredictable) result for a given key.
-func TestNegativeKEMSameWrongResult(t *testing.T) {
- sk := NewPrivateKey(KeyVariant_SIKE)
- checkErr(t, sk.Generate(rand.Reader), "error: key generation")
- pk := sk.GeneratePublicKey()
-
- ct, encSs, err := Encapsulate(rand.Reader, pk)
- checkErr(t, err, "pre-requisite for a test failed")
-
- // make ciphertext wrong
- ct[0] = ct[0] - 1
- decSs1, err := Decapsulate(sk, pk, ct)
- checkErr(t, err, "pre-requisite for a test failed")
-
- // second decapsulation must be done with same, but imported private key
- expSk := sk.Export()
-
- // creat new private key
- sk = NewPrivateKey(KeyVariant_SIKE)
- err = sk.Import(expSk)
- checkErr(t, err, "import failed")
-
- // try decapsulating again. ss2 must be same as ss1 and different than
- // original plaintext
- decSs2, err := Decapsulate(sk, pk, ct)
- checkErr(t, err, "pre-requisite for a test failed")
-
- if !bytes.Equal(decSs1, decSs2) {
- t.Error("decapsulation is insecure")
- }
-
- if bytes.Equal(encSs, decSs1) || bytes.Equal(encSs, decSs2) {
- // this test requires that decapsulation returns wrong result
- t.Errorf("test implementation error")
- }
-}
-
-func readAndCheckLine(r *bufio.Reader) []byte {
- // Read next line from buffer
- line, isPrefix, err := r.ReadLine()
- if err != nil || isPrefix {
- panic("Wrong format of input file")
- }
-
- // Function expects that line is in format "KEY = HEX_VALUE". Get
- // value, which should be a hex string
- hexst := strings.Split(string(line), "=")[1]
- hexst = strings.TrimSpace(hexst)
- // Convert value to byte string
- ret, err := hex.DecodeString(hexst)
- if err != nil {
- panic("Wrong format of input file")
- }
- return ret
-}
-
-func testKeygenSIKE(pk, sk []byte, id uint8) bool {
- // Import provided private key
- var prvKey = NewPrivateKey(KeyVariant_SIKE)
- if prvKey.Import(sk) != nil {
- panic("sike test: can't load KAT")
- }
-
- // Generate public key
- pubKey := prvKey.GeneratePublicKey()
- return bytes.Equal(pubKey.Export(), pk)
-}
-
-func testDecapsulation(pk, sk, ct, ssExpected []byte, id uint8) bool {
- var pubKey = NewPublicKey(KeyVariant_SIKE)
- var prvKey = NewPrivateKey(KeyVariant_SIKE)
- if pubKey.Import(pk) != nil || prvKey.Import(sk) != nil {
- panic("sike test: can't load KAT")
- }
-
- ssGot, err := Decapsulate(prvKey, pubKey, ct)
- if err != nil {
- panic("sike test: can't perform degcapsulation KAT")
- }
-
- return bytes.Equal(ssGot, ssExpected)
-}
-
-func TestKeyAgreement(t *testing.T) {
- testKeyAgreement(t, tdata.PkA_sidh, tdata.PrA_sidh, tdata.PkB_sidh, tdata.PrB_sidh)
-}
-
-// Same values as in sike_test.cc
-func TestDecapsulation(t *testing.T) {
- var sk = [16 + 28]byte{
- 0x04, 0x5E, 0x01, 0x42, 0xB8, 0x2F, 0xE1, 0x9A, 0x38, 0x25,
- 0x92, 0xE7, 0xDC, 0xBA, 0xF7, 0x1B, 0xB1, 0xFD, 0x34, 0x42,
- 0xDB, 0x02, 0xBC, 0x9D, 0x4C, 0xD0, 0x72, 0x34, 0x4D, 0xBD,
- 0x06, 0xDF, 0x1C, 0x7D, 0x0A, 0x88, 0xB2, 0x50, 0xC4, 0xF6,
- 0xAE, 0xE8, 0x25, 0x01,
- }
-
- var pk = [330]byte{
- 0x6D, 0x8D, 0xF5, 0x7B, 0xCD, 0x47, 0xCA, 0xCB, 0x7A, 0x38,
- 0xB7, 0xA6, 0x90, 0xB7, 0x37, 0x03, 0xD4, 0x6F, 0x27, 0x73,
- 0x74, 0x17, 0x5A, 0xA4, 0x0D, 0xC6, 0x81, 0xAD, 0xDB, 0xF7,
- 0x18, 0xB2, 0x3C, 0x30, 0xCF, 0xAA, 0x08, 0x11, 0x91, 0xCC,
- 0x27, 0x4E, 0xF1, 0xA6, 0xB7, 0xDA, 0xD2, 0xCF, 0x99, 0x7F,
- 0xF7, 0xE1, 0xD0, 0xCE, 0x00, 0xD2, 0x4B, 0xA4, 0x33, 0xB4,
- 0x87, 0x01, 0x3F, 0x02, 0xF7, 0xF9, 0xDE, 0xC3, 0x60, 0x62,
- 0xDA, 0x3F, 0x74, 0xA9, 0x44, 0xBE, 0x19, 0xD5, 0x03, 0x2A,
- 0x79, 0x8C, 0xA7, 0xFF, 0xEA, 0xB3, 0xBB, 0xB5, 0xD4, 0x1D,
- 0x8F, 0x92, 0xCE, 0x62, 0x6E, 0x99, 0x24, 0xD7, 0x57, 0xFA,
- 0xCD, 0xB6, 0xE2, 0x8E, 0xFD, 0x22, 0x0E, 0x31, 0x21, 0x01,
- 0x8D, 0x79, 0xF8, 0x3E, 0x27, 0xEC, 0x43, 0x40, 0xDB, 0x82,
- 0xE5, 0xEB, 0x6C, 0x97, 0x66, 0x29, 0x15, 0x68, 0xB7, 0x4D,
- 0x84, 0xD1, 0x8A, 0x0B, 0x12, 0x36, 0x2C, 0x0C, 0x0A, 0x6E,
- 0x4E, 0xDE, 0xA5, 0x8A, 0xDE, 0x77, 0xDD, 0x70, 0x49, 0x73,
- 0xAC, 0x27, 0x6D, 0x8D, 0x25, 0x9A, 0xE4, 0x25, 0xE8, 0x95,
- 0x8F, 0xFE, 0x90, 0x3B, 0x00, 0x69, 0x20, 0xE8, 0x7C, 0xA5,
- 0xF5, 0x79, 0xC0, 0x61, 0x51, 0x91, 0x35, 0x25, 0x3F, 0x17,
- 0x2F, 0x70, 0x73, 0xF0, 0x89, 0xB5, 0xC8, 0x25, 0xB8, 0xE5,
- 0x7E, 0x34, 0xDD, 0x11, 0xE5, 0xD6, 0xC3, 0xD5, 0x29, 0x89,
- 0xC6, 0x2C, 0x99, 0x53, 0x1D, 0x2C, 0x77, 0xB0, 0xB6, 0xA1,
- 0xBD, 0x79, 0xFB, 0x4A, 0xC2, 0x48, 0x4C, 0x62, 0x51, 0x00,
- 0xE3, 0x91, 0x2A, 0xCB, 0x84, 0x03, 0x5D, 0x2D, 0xC8, 0x33,
- 0xE9, 0x14, 0xBF, 0x74, 0x21, 0xBC, 0xF4, 0x76, 0xE5, 0x42,
- 0xB8, 0xBD, 0xE2, 0xE7, 0x20, 0x95, 0x54, 0xF2, 0xED, 0xC0,
- 0x79, 0x38, 0x1E, 0xD2, 0xEA, 0x1A, 0x63, 0x85, 0xE7, 0x3A,
- 0xDA, 0xAD, 0xAB, 0x1B, 0x1E, 0x19, 0x9E, 0x73, 0xD0, 0x10,
- 0x2E, 0x38, 0xAC, 0x8B, 0x00, 0x6A, 0x30, 0x2C, 0x3D, 0x70,
- 0x8E, 0x39, 0x6D, 0xC0, 0x12, 0x61, 0x7D, 0x2A, 0x0A, 0x04,
- 0x95, 0x8E, 0x09, 0x3C, 0x7B, 0xEC, 0x2E, 0xBC, 0xE8, 0xE8,
- 0xE8, 0x37, 0x29, 0xC4, 0x7E, 0x76, 0x48, 0xB9, 0x3B, 0x72,
- 0xE5, 0x99, 0x9B, 0xF9, 0xE3, 0x99, 0x72, 0x3F, 0x35, 0x29,
- 0x85, 0xE0, 0xC8, 0xBF, 0xB1, 0x6B, 0xB1, 0x6E, 0x72, 0x00,
- }
-
- var ct = [330 + 16]byte{
- 0xFF, 0xEB, 0xEF, 0x4A, 0xC0, 0x57, 0x0F, 0x26, 0xAC, 0x76,
- 0xA8, 0xB0, 0xA3, 0x5D, 0x9C, 0xD9, 0x25, 0xD1, 0x7F, 0x92,
- 0x5D, 0xF4, 0x23, 0x34, 0xC3, 0x03, 0x10, 0xE1, 0xB0, 0x24,
- 0x9B, 0x44, 0x58, 0x26, 0x13, 0x56, 0x83, 0x43, 0x72, 0x69,
- 0x28, 0x0D, 0x55, 0x07, 0x1F, 0xDB, 0xC0, 0x23, 0x34, 0x83,
- 0x1A, 0x09, 0x9B, 0x80, 0x00, 0x64, 0x56, 0xDC, 0x79, 0x7A,
- 0xD2, 0xCE, 0x23, 0xC9, 0x72, 0x27, 0xFC, 0x8D, 0xAB, 0xBF,
- 0xD3, 0x17, 0xF6, 0x91, 0x7B, 0x15, 0x93, 0x83, 0x8A, 0x4F,
- 0x6C, 0xCA, 0x4A, 0x94, 0xDA, 0xC7, 0x9D, 0xB6, 0xD6, 0xBA,
- 0xBD, 0x81, 0x9A, 0x78, 0xE5, 0xE5, 0xBE, 0x17, 0xBC, 0xCB,
- 0xC8, 0x23, 0x80, 0x5F, 0x75, 0xF8, 0xDB, 0x51, 0x55, 0x00,
- 0x25, 0x33, 0x52, 0x64, 0xB2, 0xD6, 0xD8, 0x9A, 0x2A, 0x9E,
- 0x29, 0x99, 0x13, 0x33, 0xE2, 0xA7, 0x98, 0xAC, 0xD7, 0x79,
- 0x5C, 0x2F, 0xBA, 0x07, 0xC3, 0x03, 0x37, 0xD6, 0xE6, 0xB5,
- 0xA1, 0xF5, 0x29, 0xB6, 0xF6, 0xC0, 0x5C, 0x44, 0x68, 0x2B,
- 0x0B, 0xF5, 0x00, 0x01, 0x44, 0xD5, 0xCC, 0x23, 0xB5, 0x27,
- 0x4F, 0xCA, 0xB4, 0x05, 0x01, 0xF9, 0xD4, 0x41, 0xE0, 0xE1,
- 0x1E, 0xCF, 0xA9, 0xBC, 0x79, 0xD7, 0xD5, 0xF5, 0x3C, 0xE6,
- 0x93, 0xF4, 0x6C, 0x84, 0x5A, 0x2C, 0x4B, 0xE4, 0x91, 0xB2,
- 0xB2, 0xB8, 0xAD, 0x74, 0x9A, 0x69, 0x79, 0x4C, 0x84, 0xB7,
- 0xBF, 0xF1, 0x68, 0x4B, 0xAE, 0x0F, 0x7F, 0x45, 0x3B, 0x18,
- 0x3F, 0xFA, 0x00, 0x48, 0xE0, 0x3A, 0xE2, 0xC0, 0xAE, 0x00,
- 0xCE, 0x90, 0x28, 0xA4, 0x1B, 0xBE, 0xCA, 0x0C, 0x21, 0x29,
- 0x64, 0x30, 0x5E, 0x35, 0xAD, 0xFD, 0x83, 0x47, 0x40, 0x6D,
- 0x15, 0x56, 0xFC, 0xF8, 0x5F, 0xAB, 0x81, 0xFE, 0x6B, 0xE9,
- 0x6B, 0xED, 0x27, 0x35, 0x7C, 0xD8, 0x2C, 0xD4, 0xF2, 0x11,
- 0xE6, 0xAF, 0xDF, 0xB8, 0x91, 0x96, 0xEB, 0xF7, 0x4C, 0x8D,
- 0x70, 0x77, 0x90, 0x81, 0x00, 0x09, 0x19, 0x27, 0x8A, 0x9E,
- 0xB6, 0x1A, 0xE9, 0xAC, 0x6C, 0xC9, 0xF8, 0xEA, 0xA2, 0x34,
- 0xB8, 0xAC, 0xB3, 0xB3, 0x68, 0xA1, 0xB7, 0x29, 0x55, 0xCA,
- 0x40, 0x23, 0x92, 0x5C, 0x0C, 0x79, 0x6B, 0xD6, 0x9F, 0x5B,
- 0xD2, 0xE6, 0xAE, 0x04, 0xCB, 0xEC, 0xC7, 0x88, 0x18, 0xDB,
- 0x7A, 0xE6, 0xD6, 0xC9, 0x39, 0xFD, 0x93, 0x9B, 0xC8, 0x01,
- 0x6F, 0x3E, 0x6C, 0x90, 0x3E, 0x73, 0x76, 0x99, 0x7C, 0x48,
- 0xDA, 0x68, 0x48, 0x80, 0x2B, 0x63,
- }
- var ssExp = [16]byte{
- 0xA1, 0xF9, 0x5A, 0x67, 0xB9, 0x3D, 0x1E, 0x72, 0xE8, 0xC5,
- 0x71, 0xF1, 0x4C, 0xB2, 0xAA, 0x6D,
- }
-
- var prvObj = NewPrivateKey(KeyVariant_SIKE)
- var pubObj = NewPublicKey(KeyVariant_SIKE)
-
- if pubObj.Import(pk[:]) != nil || prvObj.Import(sk[:]) != nil {
- t.Error("Can't import one of the keys")
- }
-
- res, _ := Decapsulate(prvObj, pubObj, ct[:])
- if !bytes.Equal(ssExp[:], res) {
- t.Error("Wrong decapsulation result")
- }
-}
-
-/* -------------------------------------------------------------------------
- Benchmarking
- -------------------------------------------------------------------------*/
-
-func BenchmarkSidhKeyAgreement(b *testing.B) {
- // KeyPairs
- alicePublic := convToPub(tdata.PkA_sidh, KeyVariant_SIDH_A)
- alicePrivate := convToPrv(tdata.PrA_sidh, KeyVariant_SIDH_A)
- bobPublic := convToPub(tdata.PkB_sidh, KeyVariant_SIDH_B)
- bobPrivate := convToPrv(tdata.PrB_sidh, KeyVariant_SIDH_B)
-
- for i := 0; i < b.N; i++ {
- // Derive shared secret
- DeriveSecret(bobPrivate, alicePublic)
- DeriveSecret(alicePrivate, bobPublic)
- }
-}
-
-func BenchmarkAliceKeyGenPrv(b *testing.B) {
- prv := NewPrivateKey(KeyVariant_SIDH_A)
- for n := 0; n < b.N; n++ {
- prv.Generate(rand.Reader)
- }
-}
-
-func BenchmarkBobKeyGenPrv(b *testing.B) {
- prv := NewPrivateKey(KeyVariant_SIDH_B)
- for n := 0; n < b.N; n++ {
- prv.Generate(rand.Reader)
- }
-}
-
-func BenchmarkAliceKeyGenPub(b *testing.B) {
- prv := NewPrivateKey(KeyVariant_SIDH_A)
- prv.Generate(rand.Reader)
- for n := 0; n < b.N; n++ {
- prv.GeneratePublicKey()
- }
-}
-
-func BenchmarkBobKeyGenPub(b *testing.B) {
- prv := NewPrivateKey(KeyVariant_SIDH_B)
- prv.Generate(rand.Reader)
- for n := 0; n < b.N; n++ {
- prv.GeneratePublicKey()
- }
-}
-
-func BenchmarkSharedSecretAlice(b *testing.B) {
- aPr := convToPrv(tdata.PrA_sidh, KeyVariant_SIDH_A)
- bPk := convToPub(tdata.PkB_sike, KeyVariant_SIDH_B)
- for n := 0; n < b.N; n++ {
- DeriveSecret(aPr, bPk)
- }
-}
-
-func BenchmarkSharedSecretBob(b *testing.B) {
- // m_B = 3*randint(0,3^238)
- aPk := convToPub(tdata.PkA_sidh, KeyVariant_SIDH_A)
- bPr := convToPrv(tdata.PrB_sidh, KeyVariant_SIDH_B)
- for n := 0; n < b.N; n++ {
- DeriveSecret(bPr, aPk)
- }
-}
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 8d8a068..6313673 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -1611,9 +1611,6 @@
case SSL_CURVE_CECPQ2:
nids.push_back(NID_CECPQ2);
break;
- case SSL_CURVE_CECPQ2b:
- nids.push_back(NID_CECPQ2b);
- break;
}
if (!SSL_set1_curves(ssl.get(), &nids[0], nids.size())) {
return nullptr;
@@ -1622,8 +1619,8 @@
}
if (enable_all_curves) {
static const int kAllCurves[] = {
- NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1,
- NID_X25519, NID_CECPQ2, NID_CECPQ2b,
+ NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1,
+ NID_secp521r1, NID_X25519, NID_CECPQ2,
};
if (!SSL_set1_curves(ssl.get(), kAllCurves,
OPENSSL_ARRAY_SIZE(kAllCurves))) {