diff --git a/LICENSE b/LICENSE index 2f4dfcdb04..49c41fa7af 100644 --- a/LICENSE +++ b/LICENSE @@ -181,29 +181,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -The code in third_party/sike also carries the MIT license: - -Copyright (c) Microsoft Corporation. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE - - Licenses for support code ------------------------- diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index f3e2ca477e..427bc64e9b 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -115,7 +115,6 @@ if(${ARCH} STREQUAL "aarch64") chacha/chacha-armv8.${ASM_EXT} test/trampoline-armv8.${ASM_EXT} - third_party/sike/asm/fp-armv8.${ASM_EXT} ) endif() @@ -137,7 +136,6 @@ if(${ARCH} STREQUAL "x86_64") cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT} hrss/asm/poly_rq_mul.S test/trampoline-x86_64.${ASM_EXT} - third_party/sike/asm/fp-x86_64.${ASM_EXT} ) endif() @@ -147,8 +145,6 @@ perlasm(chacha/chacha-x86.${ASM_EXT} chacha/asm/chacha-x86.pl) perlasm(chacha/chacha-x86_64.${ASM_EXT} chacha/asm/chacha-x86_64.pl) perlasm(cipher_extra/aes128gcmsiv-x86_64.${ASM_EXT} cipher_extra/asm/aes128gcmsiv-x86_64.pl) perlasm(cipher_extra/chacha20_poly1305_x86_64.${ASM_EXT} cipher_extra/asm/chacha20_poly1305_x86_64.pl) -perlasm(third_party/sike/asm/fp-x86_64.${ASM_EXT} ../third_party/sike/asm/fp-x86_64.pl) -perlasm(third_party/sike/asm/fp-armv8.${ASM_EXT} ../third_party/sike/asm/fp-armv8.pl) perlasm(test/trampoline-armv4.${ASM_EXT} test/asm/trampoline-armv4.pl) perlasm(test/trampoline-armv8.${ASM_EXT} test/asm/trampoline-armv8.pl) perlasm(test/trampoline-x86.${ASM_EXT} test/asm/trampoline-x86.pl) @@ -412,11 +408,6 @@ add_library( x509v3/v3_sxnet.c x509v3/v3_utl.c ../third_party/fiat/curve25519.c - ../third_party/sike/fpx.c - ../third_party/sike/isogeny.c - ../third_party/sike/curve_params.c - ../third_party/sike/sike.c - ../third_party/sike/asm/fp_generic.c $ @@ -537,7 +528,6 @@ add_executable( x509/x509_time_test.cc x509v3/tab_test.cc x509v3/v3name_test.cc - ../third_party/sike/sike_test.cc $ $ diff --git a/crypto/obj/obj_dat.h b/crypto/obj/obj_dat.h index 1a9bf15890..0313a08afb 100644 --- a/crypto/obj/obj_dat.h +++ b/crypto/obj/obj_dat.h @@ -57,7 +57,7 @@ /* This file is generated by crypto/obj/objects.go. */ -#define NUM_NID 961 +#define NUM_NID 960 static const uint8_t kObjectData[] = { /* NID_rsadsi */ @@ -8756,7 +8756,6 @@ static const ASN1_OBJECT kObjects[NUM_NID] = { {"KxANY", "kx-any", NID_kx_any, 0, NULL, 0}, {"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0}, {"CECPQ2", "CECPQ2", NID_CECPQ2, 0, NULL, 0}, - {"CECPQ2b", "CECPQ2b", NID_CECPQ2b, 0, NULL, 0}, }; static const unsigned kNIDsInShortNameOrder[] = { @@ -8819,7 +8818,6 @@ static const unsigned kNIDsInShortNameOrder[] = { 109 /* CAST5-ECB */, 111 /* CAST5-OFB */, 959 /* CECPQ2 */, - 960 /* CECPQ2b */, 894 /* CMAC */, 13 /* CN */, 141 /* CRLReason */, @@ -9725,7 +9723,6 @@ static const unsigned kNIDsInLongNameOrder[] = { 179 /* CA Issuers */, 785 /* CA Repository */, 959 /* CECPQ2 */, - 960 /* CECPQ2b */, 131 /* Code Signing */, 783 /* Diffie-Hellman based MAC */, 382 /* Directory */, diff --git a/crypto/obj/obj_mac.num b/crypto/obj/obj_mac.num index f2d4e8cae3..5fa839d285 100644 --- a/crypto/obj/obj_mac.num +++ b/crypto/obj/obj_mac.num @@ -948,4 +948,3 @@ auth_psk 956 kx_any 957 auth_any 958 CECPQ2 959 -CECPQ2b 960 diff --git a/crypto/obj/objects.txt b/crypto/obj/objects.txt index 6e7ecf0764..6dbb7ad77f 100644 --- a/crypto/obj/objects.txt +++ b/crypto/obj/objects.txt @@ -1337,9 +1337,6 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme # NID for CECPQ2 (no corresponding OID). : CECPQ2 -# NID for CECPQ2 (no corresponding OID). - : CECPQ2b - # See RFC 8410. 1 3 101 112 : ED25519 diff --git a/include/openssl/nid.h b/include/openssl/nid.h index cea975a314..270d443a6f 100644 --- a/include/openssl/nid.h +++ b/include/openssl/nid.h @@ -4237,9 +4237,6 @@ extern "C" { #define SN_CECPQ2 "CECPQ2" #define NID_CECPQ2 959 -#define SN_CECPQ2b "CECPQ2b" -#define NID_CECPQ2b 960 - #if defined(__cplusplus) } /* extern C */ diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index f12cacce76..48a381b93d 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -2231,7 +2231,6 @@ OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves); #define SSL_CURVE_SECP521R1 25 #define SSL_CURVE_X25519 29 #define SSL_CURVE_CECPQ2 16696 -#define SSL_CURVE_CECPQ2b 65074 // SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently // completed handshake or 0 if not applicable. diff --git a/ssl/s3_both.cc b/ssl/s3_both.cc index 58f0f8a87e..1ec596a371 100644 --- a/ssl/s3_both.cc +++ b/ssl/s3_both.cc @@ -660,8 +660,7 @@ class CipherScorer { 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 Score; diff --git a/ssl/ssl_key_share.cc b/ssl/ssl_key_share.cc index 826fb1acc5..6cac3cf22f 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 @@ class CECPQ2KeyShare : public SSLKeyShare { 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 *out_secret, - uint8_t *out_alert, Span 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 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 *out_secret, uint8_t *out_alert, - Span peer_key) override { - *out_alert = SSL_AD_INTERNAL_ERROR; - - Array 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 @@ CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = { {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 @@ UniquePtr SSLKeyShare::Create(uint16_t group_id) { return UniquePtr(New()); case SSL_CURVE_CECPQ2: return UniquePtr(New()); - case SSL_CURVE_CECPQ2b: - return UniquePtr(New()); default: return nullptr; } diff --git a/ssl/t1_lib.cc b/ssl/t1_lib.cc index cc29a832f6..e5a33ddcd1 100644 --- a/ssl/t1_lib.cc +++ b/ssl/t1_lib.cc @@ -200,7 +200,7 @@ static bool tls1_check_duplicate_extensions(const CBS *cbs) { } 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 d1cf757dd5..a4f787a9b3 100644 --- a/ssl/test/runner/common.go +++ b/ssl/test/runner/common.go @@ -151,7 +151,6 @@ const ( CurveP521 CurveID = 25 CurveX25519 CurveID = 29 CurveCECPQ2 CurveID = 16696 - CurveCECPQ2b CurveID = 65074 ) // TLS Elliptic Curve Point Formats @@ -1732,7 +1731,7 @@ func (c *Config) maxVersion(isDTLS bool) uint16 { 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 44b817ee45..24278564d9 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go @@ -210,7 +210,7 @@ func (hs *serverHandshakeState) readClientHello() error { 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 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) 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 56cfec8b8a..266163ec5b 100644 --- a/ssl/test/runner/key_agreement.go +++ b/ssl/test/runner/key_agreement.go @@ -19,7 +19,6 @@ import ( "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 @@ func (e *cecpq2Curve) finish(peerKey []byte) (preMasterSecret []byte, err error) 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 @@ func curveForCurveID(id CurveID, config *Config) (ecdhCurve, bool) { 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 @@ func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Cer 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 758566a9ca..18b01aa021 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go @@ -10449,13 +10449,12 @@ var testCurves = []struct { {"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 @@ func addCurveTests() { }, }) - // 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 @@ func addCurveTests() { 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 @@ func addCurveTests() { }, }) - // 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 @@ func addCurveTests() { }, }) - // 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 @@ func addCurveTests() { }, }) - // 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 @@ func addCurveTests() { "-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 @@ func addTLS13CipherPreferenceTests() { }, }) - // 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 @@ func addTLS13CipherPreferenceTests() { 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 @@ func addTLS13CipherPreferenceTests() { "-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 10a2ca630f..0000000000 --- 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 9d68a4fd7b..0000000000 --- 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 81725462d4..0000000000 --- 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)/

, - // 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)/ = 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/ -// * 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)/ = 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/ -// * 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 dcd6cfc469..0000000000 --- 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 2e146bc781..0000000000 --- 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 8d8a068663..6313673513 100644 --- a/ssl/test/test_config.cc +++ b/ssl/test/test_config.cc @@ -1611,9 +1611,6 @@ bssl::UniquePtr TestConfig::NewSSL( 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 @@ bssl::UniquePtr TestConfig::NewSSL( } 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))) { diff --git a/third_party/sike/LICENSE b/third_party/sike/LICENSE deleted file mode 100644 index 5cf7c8db62..0000000000 --- a/third_party/sike/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Microsoft Corporation. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE diff --git a/third_party/sike/asm/fp-armv8.pl b/third_party/sike/asm/fp-armv8.pl deleted file mode 100644 index ce19d8090e..0000000000 --- a/third_party/sike/asm/fp-armv8.pl +++ /dev/null @@ -1,915 +0,0 @@ -#! /usr/bin/env perl -# -# April 2019 -# -# Abstract: field arithmetic in aarch64 assembly for SIDH/p434 - -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } - -$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; -( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or -( $xlate="${dir}../../../crypto/perlasm/arm-xlate.pl" and -f $xlate) or -die "can't locate arm-xlate.pl"; - -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; -*STDOUT=*OUT; - -$PREFIX="sike"; - -$code.=<<___; -.section .rodata - -# p434 x 2 -.Lp434x2: - .quad 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF - .quad 0xFB82ECF5C5FFFFFF, 0xF78CB8F062B15D47 - .quad 0xD9F8BFAD038A40AC, 0x0004683E4E2EE688 - -# p434 + 1 -.Lp434p1: - .quad 0xFDC1767AE3000000, 0x7BC65C783158AEA3 - .quad 0x6CFC5FD681C52056, 0x0002341F27177344 - -.text -___ - -# Computes C0-C2 = A0 * (B0-B1) -# Inputs remain intact -sub mul64x128 { - my ($A0,$B0,$B1,$C0,$C1,$C2,$T0,$T1)=@_; - my $body=<<___; - mul $T1, $A0, $B0 - umulh $B0, $A0, $B0 - adds $C0, $C0, $C2 - adc $C1, $C1, xzr - - mul $T0, $A0, $B1 - umulh $B1, $A0, $B1 - adds $C0, $C0, $T1 - adcs $C1, $C1, $B0 - adc $C2, xzr, xzr - - adds $C1, $C1, $T0 - adc $C2, $C2, $B1 -___ - return $body; -} - -# Computes C0-C4 = A0 * (B0-B3) -# Inputs remain intact -sub mul64x256 { - my ($A0,$B0,$B1,$B2,$B3,$C0,$C1,$C2,$C3,$C4,$T0,$T1,$T2)=@_; - my $body=<<___; - mul $C0, $A0, $B0 // C0 - umulh $T0, $A0, $B0 - - mul $C1, $A0, $B1 - umulh $T1, $A0, $B1 - adds $C1, $C1, $T0 // C1 - adc $T0, xzr, xzr - - mul $C2, $A0, $B2 - umulh $T2, $A0, $B2 - adds $T1, $T0, $T1 - adcs $C2, $C2, $T1 // C2 - adc $T0, xzr, xzr - - mul $C3, $A0, $B3 - umulh $C4, $A0, $B3 - adds $T2, $T0, $T2 - adcs $C3, $C3, $T2 // C3 - adc $C4, $C4, xzr // C4 -___ - return $body; -} - -# Computes C0-C4 = (A0-A1) * (B0-B3) -# Inputs remain intact -sub mul128x256 { - my ($A0,$A1,$B0,$B1,$B2,$B3,$C0,$C1,$C2,$C3,$C4,$C5,$T0,$T1,$T2,$T3)=@_; - my $body=<<___; - mul $C0, $A0, $B0 // C0 - umulh $C3, $A0, $B0 - - mul $C1, $A0, $B1 - umulh $C2, $A0, $B1 - - mul $T0, $A1, $B0 - umulh $T1, $A1, $B0 - adds $C1, $C1, $C3 - adc $C2, $C2, xzr - - mul $T2, $A0, $B2 - umulh $T3, $A0, $B2 - adds $C1, $C1, $T0 // C1 - adcs $C2, $C2, $T1 - adc $C3, xzr, xzr - - mul $T0, $A1, $B1 - umulh $T1, $A1, $B1 - adds $C2, $C2, $T2 - adcs $C3, $C3, $T3 - adc $C4, xzr, xzr - - mul $T2, $A0, $B3 - umulh $T3, $A0, $B3 - adds $C2, $C2, $T0 // C2 - adcs $C3, $C3, $T1 - adc $C4, $C4, xzr - - mul $T0, $A1, $B2 - umulh $T1, $A1, $B2 - adds $C3, $C3, $T2 - adcs $C4, $C4, $T3 - adc $C5, xzr, xzr - - mul $T2, $A1, $B3 - umulh $T3, $A1, $B3 - adds $C3, $C3, $T0 // C3 - adcs $C4, $C4, $T1 - adc $C5, $C5, xzr - adds $C4, $C4, $T2 // C4 - adc $C5, $C5, $T3 // C5 - -___ - return $body; -} - -# Computes C0-C5 = (A0-A2) * (B0-B2) -# Inputs remain intact -sub mul192 { - my ($A0,$A1,$A2,$B0,$B1,$B2,$C0,$C1,$C2,$C3,$C4,$C5,$T0,$T1,$T2,$T3)=@_; - my $body=<<___; - - // A0 * B0 - mul $C0, $A0, $B0 // C0 - umulh $C3, $A0, $B0 - - // A0 * B1 - mul $C1, $A0, $B1 - umulh $C2, $A0, $B1 - - // A1 * B0 - mul $T0, $A1, $B0 - umulh $T1, $A1, $B0 - adds $C1, $C1, $C3 - adc $C2, $C2, xzr - - // A0 * B2 - mul $T2, $A0, $B2 - umulh $T3, $A0, $B2 - adds $C1, $C1, $T0 // C1 - adcs $C2, $C2, $T1 - adc $C3, xzr, xzr - - // A2 * B0 - mul $T0, $A2, $B0 - umulh $C4, $A2, $B0 - adds $C2, $C2, $T2 - adcs $C3, $C3, $C4 - adc $C4, xzr, xzr - - // A1 * B1 - mul $T2, $A1, $B1 - umulh $T1, $A1, $B1 - adds $C2, $C2, $T0 - adcs $C3, $C3, $T3 - adc $C4, $C4, xzr - - // A1 * B2 - mul $T0, $A1, $B2 - umulh $T3, $A1, $B2 - adds $C2, $C2, $T2 // C2 - adcs $C3, $C3, $T1 - adc $C4, $C4, xzr - - // A2 * B1 - mul $T2, $A2, $B1 - umulh $T1, $A2, $B1 - adds $C3, $C3, $T0 - adcs $C4, $C4, $T3 - adc $C5, xzr, xzr - - // A2 * B2 - mul $T0, $A2, $B2 - umulh $T3, $A2, $B2 - adds $C3, $C3, $T2 // C3 - adcs $C4, $C4, $T1 - adc $C5, $C5, xzr - - adds $C4, $C4, $T0 // C4 - adc $C5, $C5, $T3 // C5 -___ - return $body; -} -sub mul256_karatsuba { - my ($M,$A0,$A1,$A2,$A3,$B0,$B1,$B2,$B3,$C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$T0,$T1)=@_; - # (AH+AL) x (BH+BL), low part - my $mul_low=&mul64x128($A1, $C6, $T1, $C3, $C4, $C5, $C7, $A0); - # AL x BL - my $mul_albl=&mul64x128($A1, $B0, $B1, $C1, $T1, $C7, $C6, $A0); - # AH x BH - my $mul_ahbh=&mul64x128($A3, $B2, $B3, $A1, $C6, $B0, $B1, $A2); - my $body=<<___; - // A0-A1 <- AH + AL, T0 <- mask - adds $A0, $A0, $A2 - adcs $A1, $A1, $A3 - adc $T0, xzr, xzr - - // C6, T1 <- BH + BL, C7 <- mask - adds $C6, $B0, $B2 - adcs $T1, $B1, $B3 - adc $C7, xzr, xzr - - // C0-C1 <- masked (BH + BL) - sub $C2, xzr, $T0 - sub $C3, xzr, $C7 - and $C0, $C6, $C2 - and $C1, $T1, $C2 - - // C4-C5 <- masked (AH + AL), T0 <- combined carry - and $C4, $A0, $C3 - and $C5, $A1, $C3 - mul $C2, $A0, $C6 - mul $C3, $A0, $T1 - and $T0, $T0, $C7 - - // C0-C1, T0 <- (AH+AL) x (BH+BL), part 1 - adds $C0, $C4, $C0 - umulh $C4, $A0, $T1 - adcs $C1, $C5, $C1 - umulh $C5, $A0, $C6 - adc $T0, $T0, xzr - - // C2-C5 <- (AH+AL) x (BH+BL), low part - $mul_low - ldp $A0, $A1, [$M,#0] - - // C2-C5, T0 <- (AH+AL) x (BH+BL), final part - adds $C4, $C0, $C4 - umulh $C7, $A0, $B0 - umulh $T1, $A0, $B1 - adcs $C5, $C1, $C5 - mul $C0, $A0, $B0 - mul $C1, $A0, $B1 - adc $T0, $T0, xzr - - // C0-C1, T1, C7 <- AL x BL - $mul_albl - - // C2-C5, T0 <- (AH+AL) x (BH+BL) - ALxBL - mul $A0, $A2, $B2 - umulh $B0, $A2, $B2 - subs $C2, $C2, $C0 - sbcs $C3, $C3, $C1 - sbcs $C4, $C4, $T1 - mul $A1, $A2, $B3 - umulh $C6, $A2, $B3 - sbcs $C5, $C5, $C7 - sbc $T0, $T0, xzr - - // A0, A1, C6, B0 <- AH x BH - $mul_ahbh - - // C2-C5, T0 <- (AH+AL) x (BH+BL) - ALxBL - AHxBH - subs $C2, $C2, $A0 - sbcs $C3, $C3, $A1 - sbcs $C4, $C4, $C6 - sbcs $C5, $C5, $B0 - sbc $T0, $T0, xzr - - adds $C2, $C2, $T1 - adcs $C3, $C3, $C7 - adcs $C4, $C4, $A0 - adcs $C5, $C5, $A1 - adcs $C6, $T0, $C6 - adc $C7, $B0, xzr -___ - return $body; -} - -# 512-bit integer multiplication using Karatsuba (two levels), -# Comba (lower level). -# Operation: c [x2] = a [x0] * b [x1] -sub mul { - # (AH+AL) x (BH+BL), low part - my $mul_kc_low=&mul256_karatsuba( - "x2", # M0 - "x3","x4","x5","x6", # A0-A3 - "x10","x11","x12","x13", # B0-B3 - "x8","x9","x19","x20","x21","x22","x23","x24", # C0-C7 - "x25","x26"); # TMP - # AL x BL - my $mul_albl=&mul256_karatsuba( - "x0", # M0f - "x3","x4","x5","x6", # A0-A3 - "x10","x11","x12","x13", # B0-B3 - "x21","x22","x23","x24","x25","x26","x27","x28",# C0-C7 - "x8","x9"); # TMP - # AH x BH - my $mul_ahbh=&mul192( - "x3","x4","x5", # A0-A2 - "x10","x11","x12", # B0-B2 - "x21","x22","x23","x24","x25","x26", # C0-C5 - "x8","x9","x27","x28"); # TMP - - my $body=<<___; - .global ${PREFIX}_mpmul - .align 4 - ${PREFIX}_mpmul: - stp x29, x30, [sp,#-96]! - add x29, sp, #0 - stp x19, x20, [sp,#16] - stp x21, x22, [sp,#32] - stp x23, x24, [sp,#48] - stp x25, x26, [sp,#64] - stp x27, x28, [sp,#80] - - ldp x3, x4, [x0] - ldp x5, x6, [x0,#16] - ldp x7, x8, [x0,#32] - ldr x9, [x0,#48] - ldp x10, x11, [x1,#0] - ldp x12, x13, [x1,#16] - ldp x14, x15, [x1,#32] - ldr x16, [x1,#48] - - // x3-x7 <- AH + AL, x7 <- carry - adds x3, x3, x7 - adcs x4, x4, x8 - adcs x5, x5, x9 - adcs x6, x6, xzr - adc x7, xzr, xzr - - // x10-x13 <- BH + BL, x8 <- carry - adds x10, x10, x14 - adcs x11, x11, x15 - adcs x12, x12, x16 - adcs x13, x13, xzr - adc x8, xzr, xzr - - // x9 <- combined carry - and x9, x7, x8 - // x7-x8 <- mask - sub x7, xzr, x7 - sub x8, xzr, x8 - - // x15-x19 <- masked (BH + BL) - and x14, x10, x7 - and x15, x11, x7 - and x16, x12, x7 - and x17, x13, x7 - - // x20-x23 <- masked (AH + AL) - and x20, x3, x8 - and x21, x4, x8 - and x22, x5, x8 - and x23, x6, x8 - - // x15-x19, x7 <- masked (AH+AL) + masked (BH+BL), step 1 - adds x14, x14, x20 - adcs x15, x15, x21 - adcs x16, x16, x22 - adcs x17, x17, x23 - adc x7, x9, xzr - - // x8-x9,x19,x20-x24 <- (AH+AL) x (BH+BL), low part - stp x3, x4, [x2,#0] - $mul_kc_low - - // x15-x19, x7 <- (AH+AL) x (BH+BL), final step - adds x14, x14, x21 - adcs x15, x15, x22 - adcs x16, x16, x23 - adcs x17, x17, x24 - adc x7, x7, xzr - - // Load AL - ldp x3, x4, [x0] - ldp x5, x6, [x0,#16] - // Load BL - ldp x10, x11, [x1,#0] - ldp x12, x13, [x1,#16] - - // Temporarily store x8 in x2 - stp x8, x9, [x2,#0] - // x21-x28 <- AL x BL - $mul_albl - // Restore x8 - ldp x8, x9, [x2,#0] - - // x8-x10,x20,x15-x17,x19 <- maskd (AH+AL) x (BH+BL) - ALxBL - subs x8, x8, x21 - sbcs x9, x9, x22 - sbcs x19, x19, x23 - sbcs x20, x20, x24 - sbcs x14, x14, x25 - sbcs x15, x15, x26 - sbcs x16, x16, x27 - sbcs x17, x17, x28 - sbc x7, x7, xzr - - // Store ALxBL, low - stp x21, x22, [x2] - stp x23, x24, [x2,#16] - - // Load AH - ldp x3, x4, [x0,#32] - ldr x5, [x0,#48] - // Load BH - ldp x10, x11, [x1,#32] - ldr x12, [x1,#48] - - adds x8, x8, x25 - adcs x9, x9, x26 - adcs x19, x19, x27 - adcs x20, x20, x28 - adc x1, xzr, xzr - - add x0, x0, #32 - // Temporarily store x8,x9 in x2 - stp x8,x9, [x2,#32] - // x21-x28 <- AH x BH - $mul_ahbh - // Restore x8,x9 - ldp x8,x9, [x2,#32] - - neg x1, x1 - - // x8-x9,x19,x20,x14-x17 <- (AH+AL) x (BH+BL) - ALxBL - AHxBH - subs x8, x8, x21 - sbcs x9, x9, x22 - sbcs x19, x19, x23 - sbcs x20, x20, x24 - sbcs x14, x14, x25 - sbcs x15, x15, x26 - sbcs x16, x16, xzr - sbcs x17, x17, xzr - sbc x7, x7, xzr - - // Store (AH+AL) x (BH+BL) - ALxBL - AHxBH, low - stp x8, x9, [x2,#32] - stp x19, x20, [x2,#48] - - adds x1, x1, #1 - adcs x14, x14, x21 - adcs x15, x15, x22 - adcs x16, x16, x23 - adcs x17, x17, x24 - adcs x25, x7, x25 - adc x26, x26, xzr - - stp x14, x15, [x2,#64] - stp x16, x17, [x2,#80] - stp x25, x26, [x2,#96] - - ldp x19, x20, [x29,#16] - ldp x21, x22, [x29,#32] - ldp x23, x24, [x29,#48] - ldp x25, x26, [x29,#64] - ldp x27, x28, [x29,#80] - ldp x29, x30, [sp],#96 - ret -___ - return $body; -} -$code.=&mul(); - -# Montgomery reduction -# Based on method described in Faz-Hernandez et al. https://eprint.iacr.org/2017/1015 -# Operation: mc [x1] = ma [x0] -# NOTE: ma=mc is not allowed -sub rdc { - my $mul01=&mul128x256( - "x2","x3", # A0-A1 - "x23","x24","x25","x26", # B0-B3 - "x4","x5","x6","x7","x8","x9", # C0-C5 - "x10","x11","x27","x28"); # TMP - my $mul23=&mul128x256( - "x2","x10", # A0-A1 - "x23","x24","x25","x26", # B0-B3 - "x4","x5","x6","x7","x8","x9", # C0-C5 - "x0","x3","x27","x28"); # TMP - my $mul45=&mul128x256( - "x11","x12", # A0-A1 - "x23","x24","x25","x26", # B0-B3 - "x4","x5","x6","x7","x8","x9", # C0-C5 - "x10","x3","x27","x28"); # TMP - my $mul67=&mul64x256( - "x13", # A0 - "x23","x24","x25","x26", # B0-B3 - "x4","x5","x6","x7","x8", # C0-C4 - "x10","x27","x28"); # TMP - my $body=<<___; - .global ${PREFIX}_fprdc - .align 4 - ${PREFIX}_fprdc: - stp x29, x30, [sp, #-96]! - add x29, sp, xzr - stp x19, x20, [sp,#16] - stp x21, x22, [sp,#32] - stp x23, x24, [sp,#48] - stp x25, x26, [sp,#64] - stp x27, x28, [sp,#80] - - ldp x2, x3, [x0,#0] // a[0-1] - - // Load the prime constant - adrp x26, :pg_hi21:.Lp434p1 - add x26, x26, :lo12:.Lp434p1 - ldp x23, x24, [x26, #0x0] - ldp x25, x26, [x26,#0x10] - - // a[0-1] * p434+1 - $mul01 - - ldp x10, x11, [x0, #0x18] - ldp x12, x13, [x0, #0x28] - ldp x14, x15, [x0, #0x38] - ldp x16, x17, [x0, #0x48] - ldp x19, x20, [x0, #0x58] - ldr x21, [x0, #0x68] - - adds x10, x10, x4 - adcs x11, x11, x5 - adcs x12, x12, x6 - adcs x13, x13, x7 - adcs x14, x14, x8 - adcs x15, x15, x9 - adcs x22, x16, xzr - adcs x17, x17, xzr - adcs x19, x19, xzr - adcs x20, x20, xzr - adc x21, x21, xzr - - ldr x2, [x0,#0x10] // a[2] - // a[2-3] * p434+1 - $mul23 - - adds x12, x12, x4 - adcs x13, x13, x5 - adcs x14, x14, x6 - adcs x15, x15, x7 - adcs x16, x22, x8 - adcs x17, x17, x9 - adcs x22, x19, xzr - adcs x20, x20, xzr - adc x21, x21, xzr - - $mul45 - adds x14, x14, x4 - adcs x15, x15, x5 - adcs x16, x16, x6 - adcs x17, x17, x7 - adcs x19, x22, x8 - adcs x20, x20, x9 - adc x22, x21, xzr - - stp x14, x15, [x1, #0x0] // C0, C1 - - $mul67 - adds x16, x16, x4 - adcs x17, x17, x5 - adcs x19, x19, x6 - adcs x20, x20, x7 - adc x21, x22, x8 - - str x16, [x1, #0x10] - stp x17, x19, [x1, #0x18] - stp x20, x21, [x1, #0x28] - - ldp x19, x20, [x29,#16] - ldp x21, x22, [x29,#32] - ldp x23, x24, [x29,#48] - ldp x25, x26, [x29,#64] - ldp x27, x28, [x29,#80] - ldp x29, x30, [sp],#96 - ret -___ -} -$code.=&rdc(); - -# Field addition -# Operation: c [x2] = a [x0] + b [x1] -$code.=<<___; - .global ${PREFIX}_fpadd - .align 4 - ${PREFIX}_fpadd: - stp x29,x30, [sp,#-16]! - add x29, sp, #0 - - ldp x3, x4, [x0,#0] - ldp x5, x6, [x0,#16] - ldp x7, x8, [x0,#32] - ldr x9, [x0,#48] - ldp x11, x12, [x1,#0] - ldp x13, x14, [x1,#16] - ldp x15, x16, [x1,#32] - ldr x17, [x1,#48] - - // Add a + b - adds x3, x3, x11 - adcs x4, x4, x12 - adcs x5, x5, x13 - adcs x6, x6, x14 - adcs x7, x7, x15 - adcs x8, x8, x16 - adc x9, x9, x17 - - // Subtract 2xp434 - adrp x17, :pg_hi21:.Lp434x2 - add x17, x17, :lo12:.Lp434x2 - ldp x11, x12, [x17, #0] - ldp x13, x14, [x17, #16] - ldp x15, x16, [x17, #32] - subs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x12 - sbcs x6, x6, x13 - sbcs x7, x7, x14 - sbcs x8, x8, x15 - sbcs x9, x9, x16 - sbc x0, xzr, xzr // x0 can be reused now - - // Add 2xp434 anded with the mask in x0 - and x11, x11, x0 - and x12, x12, x0 - and x13, x13, x0 - and x14, x14, x0 - and x15, x15, x0 - and x16, x16, x0 - - adds x3, x3, x11 - adcs x4, x4, x12 - adcs x5, x5, x12 - adcs x6, x6, x13 - adcs x7, x7, x14 - adcs x8, x8, x15 - adc x9, x9, x16 - - stp x3, x4, [x2,#0] - stp x5, x6, [x2,#16] - stp x7, x8, [x2,#32] - str x9, [x2,#48] - - ldp x29, x30, [sp],#16 - ret -___ - -# Field subtraction -# Operation: c [x2] = a [x0] - b [x1] -$code.=<<___; - .global ${PREFIX}_fpsub - .align 4 - ${PREFIX}_fpsub: - stp x29, x30, [sp,#-16]! - add x29, sp, #0 - - ldp x3, x4, [x0,#0] - ldp x5, x6, [x0,#16] - ldp x7, x8, [x0,#32] - ldr x9, [x0,#48] - ldp x11, x12, [x1,#0] - ldp x13, x14, [x1,#16] - ldp x15, x16, [x1,#32] - ldr x17, [x1,#48] - - // Subtract a - b - subs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - sbcs x7, x7, x15 - sbcs x8, x8, x16 - sbcs x9, x9, x17 - sbc x0, xzr, xzr - - // Add 2xp434 anded with the mask in x0 - adrp x17, :pg_hi21:.Lp434x2 - add x17, x17, :lo12:.Lp434x2 - - // First half - ldp x11, x12, [x17, #0] - ldp x13, x14, [x17, #16] - ldp x15, x16, [x17, #32] - - // Add 2xp434 anded with the mask in x0 - and x11, x11, x0 - and x12, x12, x0 - and x13, x13, x0 - and x14, x14, x0 - and x15, x15, x0 - and x16, x16, x0 - - adds x3, x3, x11 - adcs x4, x4, x12 - adcs x5, x5, x12 - adcs x6, x6, x13 - adcs x7, x7, x14 - adcs x8, x8, x15 - adc x9, x9, x16 - - stp x3, x4, [x2,#0] - stp x5, x6, [x2,#16] - stp x7, x8, [x2,#32] - str x9, [x2,#48] - - ldp x29, x30, [sp],#16 - ret -___ - -# 434-bit multiprecision addition -# Operation: c [x2] = a [x0] + b [x1] -$code.=<<___; - .global ${PREFIX}_mpadd_asm - .align 4 - ${PREFIX}_mpadd_asm: - stp x29, x30, [sp,#-16]! - add x29, sp, #0 - - ldp x3, x4, [x0,#0] - ldp x5, x6, [x0,#16] - ldp x7, x8, [x0,#32] - ldr x9, [x0,#48] - ldp x11, x12, [x1,#0] - ldp x13, x14, [x1,#16] - ldp x15, x16, [x1,#32] - ldr x17, [x1,#48] - - adds x3, x3, x11 - adcs x4, x4, x12 - adcs x5, x5, x13 - adcs x6, x6, x14 - adcs x7, x7, x15 - adcs x8, x8, x16 - adc x9, x9, x17 - - stp x3, x4, [x2,#0] - stp x5, x6, [x2,#16] - stp x7, x8, [x2,#32] - str x9, [x2,#48] - - ldp x29, x30, [sp],#16 - ret -___ - -# 2x434-bit multiprecision subtraction -# Operation: c [x2] = a [x0] - b [x1]. -# Returns borrow mask -$code.=<<___; - .global ${PREFIX}_mpsubx2_asm - .align 4 - ${PREFIX}_mpsubx2_asm: - stp x29, x30, [sp,#-16]! - add x29, sp, #0 - - ldp x3, x4, [x0,#0] - ldp x5, x6, [x0,#16] - ldp x11, x12, [x1,#0] - ldp x13, x14, [x1,#16] - subs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - ldp x7, x8, [x0,#32] - ldp x9, x10, [x0,#48] - ldp x11, x12, [x1,#32] - ldp x13, x14, [x1,#48] - sbcs x7, x7, x11 - sbcs x8, x8, x12 - sbcs x9, x9, x13 - sbcs x10, x10, x14 - - stp x3, x4, [x2,#0] - stp x5, x6, [x2,#16] - stp x7, x8, [x2,#32] - stp x9, x10, [x2,#48] - - ldp x3, x4, [x0,#64] - ldp x5, x6, [x0,#80] - ldp x11, x12, [x1,#64] - ldp x13, x14, [x1,#80] - sbcs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - ldp x7, x8, [x0,#96] - ldp x11, x12, [x1,#96] - sbcs x7, x7, x11 - sbcs x8, x8, x12 - sbc x0, xzr, xzr - - stp x3, x4, [x2,#64] - stp x5, x6, [x2,#80] - stp x7, x8, [x2,#96] - - ldp x29, x30, [sp],#16 - ret -___ - - -# Double 2x434-bit multiprecision subtraction -# Operation: c [x2] = c [x2] - a [x0] - b [x1] -$code.=<<___; - .global ${PREFIX}_mpdblsubx2_asm - .align 4 - ${PREFIX}_mpdblsubx2_asm: - stp x29, x30, [sp, #-16]! - add x29, sp, #0 - - ldp x3, x4, [x2, #0] - ldp x5, x6, [x2,#16] - ldp x7, x8, [x2,#32] - - ldp x11, x12, [x0, #0] - ldp x13, x14, [x0,#16] - ldp x15, x16, [x0,#32] - - subs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - sbcs x7, x7, x15 - sbcs x8, x8, x16 - - // x9 stores carry - adc x9, xzr, xzr - - ldp x11, x12, [x1, #0] - ldp x13, x14, [x1,#16] - ldp x15, x16, [x1,#32] - subs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - sbcs x7, x7, x15 - sbcs x8, x8, x16 - adc x9, x9, xzr - - stp x3, x4, [x2, #0] - stp x5, x6, [x2,#16] - stp x7, x8, [x2,#32] - - ldp x3, x4, [x2,#48] - ldp x5, x6, [x2,#64] - ldp x7, x8, [x2,#80] - - ldp x11, x12, [x0,#48] - ldp x13, x14, [x0,#64] - ldp x15, x16, [x0,#80] - - // x9 = 2 - x9 - neg x9, x9 - add x9, x9, #2 - - subs x3, x3, x9 - sbcs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - sbcs x7, x7, x15 - sbcs x8, x8, x16 - adc x9, xzr, xzr - - ldp x11, x12, [x1,#48] - ldp x13, x14, [x1,#64] - ldp x15, x16, [x1,#80] - subs x3, x3, x11 - sbcs x4, x4, x12 - sbcs x5, x5, x13 - sbcs x6, x6, x14 - sbcs x7, x7, x15 - sbcs x8, x8, x16 - adc x9, x9, xzr - - stp x3, x4, [x2,#48] - stp x5, x6, [x2,#64] - stp x7, x8, [x2,#80] - - ldp x3, x4, [x2,#96] - ldp x11, x12, [x0,#96] - ldp x13, x14, [x1,#96] - - // x9 = 2 - x9 - neg x9, x9 - add x9, x9, #2 - - subs x3, x3, x9 - sbcs x3, x3, x11 - sbcs x4, x4, x12 - subs x3, x3, x13 - sbc x4, x4, x14 - stp x3, x4, [x2,#96] - - ldp x29, x30, [sp],#16 - ret -___ - -foreach (split("\n",$code)) { - s/\`([^\`]*)\`/eval($1)/ge; - print $_,"\n"; -} - -close STDOUT; diff --git a/third_party/sike/asm/fp-x86_64.pl b/third_party/sike/asm/fp-x86_64.pl deleted file mode 100755 index cffde1a821..0000000000 --- a/third_party/sike/asm/fp-x86_64.pl +++ /dev/null @@ -1,1626 +0,0 @@ -#! /usr/bin/env perl -# -# April 2019 -# -# Abstract: field arithmetic in x64 assembly for SIDH/p434 - -$flavour = shift; -$output = shift; -if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } - -$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; -( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or -( $xlate="${dir}../../../crypto/perlasm/x86_64-xlate.pl" and -f $xlate) or -die "can't locate x86_64-xlate.pl"; - -open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; -*STDOUT=*OUT; - -$PREFIX="sike"; -$bmi2_adx = 1; - -$code.=<<___; -.text - -# p434 x 2 -.Lp434x2: -.quad 0xFFFFFFFFFFFFFFFE -.quad 0xFFFFFFFFFFFFFFFF -.quad 0xFB82ECF5C5FFFFFF -.quad 0xF78CB8F062B15D47 -.quad 0xD9F8BFAD038A40AC -.quad 0x0004683E4E2EE688 - -# p434 + 1 -.Lp434p1: -.quad 0xFDC1767AE3000000 -.quad 0x7BC65C783158AEA3 -.quad 0x6CFC5FD681C52056 -.quad 0x0002341F27177344 - -.extern OPENSSL_ia32cap_P -.hidden OPENSSL_ia32cap_P -___ - -# Jump to alternative implemenatation provided as an -# argument in case CPU supports ADOX/ADCX and MULX instructions. -sub alt_impl { - $jmp_func = shift; - - $body=<<___; - lea OPENSSL_ia32cap_P(%rip), %rcx - mov 8(%rcx), %rcx - and \$0x80100, %ecx - cmp \$0x80100, %ecx - je $jmp_func - -___ - return $body -} - -# Performs schoolbook multiplication of 2 192-bit numbers. Uses -# MULX instruction. Result is stored in 192 bits pointed by $DST. -sub mul192 { - my ($idxM0,$M0,$idxM1,$M1,$idxDST,$DST,$T0,$T1,$T2,$T3,$T4,$T5,$T6)=@_; - my ($ML0,$ML8,$ML16)=map("$idxM0+$_($M0)",(0,8,16)); - my ($MR0,$MR8,$MR16)=map("$idxM1+$_($M1)",(0,8,16)); - my ($D0,$D1,$D2,$D3,$D4,$D5)=map("$idxDST+$_($DST)",(0,8,16,24,32,40)); - - $body=<<___; - mov $ML0, %rdx - mulx $MR0, $T1, $T0 # T0:T1 = A0*B0 - mov $T1, $D0 # DST0 - mulx $MR8, $T2, $T1 # T1:T2 = A0*B1 - xor %rax, %rax - adox $T2, $T0 - mulx $MR16,$T3, $T2 # T2:T3 = A0*B2 - adox $T3, $T1 - - mov $ML8, %rdx - mulx $MR0, $T4, $T3 # T3:T4 = A1*B0 - adox %rax, $T2 - xor %rax, %rax - - mulx $MR8, $T6, $T5 # T6:T7 = A1*B1 - adox $T0, $T4 - mov $T4, $D1 # DST1 - adcx $T6, $T3 - - mulx $MR16,$T0, $T6 # T6:T0 = A1*B2 - adox $T1, $T3 - adcx $T0, $T5 - adcx %rax, $T6 - adox $T2, $T5 - - mov $ML16,%rdx - mulx $MR0, $T0, $T1 # T1:T0 = A2*B0 - adox %rax, $T6 - xor %rax, %rax - - mulx $MR8, $T2, $T4 # T4:T2 = A2*B1 - adox $T3, $T0 - mov $T0, $D2 # DST2 - adcx $T5, $T1 - - mulx $MR16,$T3, $T0 # T0:T3 = A2*B2 - adcx $T6, $T4 - adcx %rax, $T0 - adox $T2, $T1 - adox $T4, $T3 - adox %rax, $T0 - mov $T1, $D3 # DST3 - mov $T3, $D4 # DST4 - mov $T0, $D5 # DST5 - -___ - return $body; -} - -# Performs schoolbook multiplication of 2 256-bit numbers. Uses -# MULX instruction. Result is stored in 256 bits pointed by $DST. -sub mul256 { - my ($idxM0,$M0,$idxM1,$M1,$idxDST,$DST,$T0,$T1,$T2,$T3,$T4,$T5,$T6,$T7,$T8,$T9)=@_; - my ($ML0,$ML8,$ML16,$ML24)=map("$idxM0+$_($M0)",(0,8,16,24)); - my ($MR0,$MR8,$MR16,$MR24)=map("$idxM1+$_($M1)",(0,8,16,24)); - my ($D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7)=map("$idxDST+$_($DST)",(0,8,16,24,32,40,48,56)); - - $body=<<___; - mov $ML0, %rdx - mulx $MR0, $T1, $T0 # T0:T1 = A0*B0 - mov $T1, $D0 # DST0_final - mulx $MR8, $T2, $T1 # T1:T2 = A0*B1 - xor %rax, %rax - adox $T2, $T0 - mulx $MR16,$T3, $T2 # T2:T3 = A0*B2 - adox $T3, $T1 - mulx $MR24,$T4, $T3 # T3:T4 = A0*B3 - adox $T4, $T2 - - mov $ML8, %rdx - mulx $MR0, $T4, $T5 # T5:T4 = A1*B0 - adox %rax, $T3 - xor %rax, %rax - mulx $MR8, $T7, $T6 # T6:T7 = A1*B1 - adox $T0, $T4 - mov $T4, $D1 # DST1_final - adcx $T7, $T5 - mulx $MR16,$T8, $T7 # T7:T8 = A1*B2 - adcx $T8, $T6 - adox $T1, $T5 - mulx $MR24,$T9, $T8 # T8:T9 = A1*B3 - adcx $T9, $T7 - adcx %rax, $T8 - adox $T2, $T6 - - mov $ML16,%rdx - mulx $MR0, $T0, $T1 # T1:T0 = A2*B0 - adox $T3, $T7 - adox %rax, $T8 - xor %rax, %rax - mulx $MR8, $T3, $T2 # T2:T3 = A2*B1 - adox $T5, $T0 - mov $T0, $D2 # DST2_final - adcx $T3, $T1 - mulx $MR16,$T4, $T3 # T3:T4 = A2*B2 - adcx $T4, $T2 - adox $T6, $T1 - mulx $MR24,$T9, $T4 # T3:T4 = A2*B3 - adcx $T9, $T3 - adcx %rax, $T4 - - adox $T7, $T2 - adox $T8, $T3 - adox %rax, $T4 - - mov $ML24,%rdx - mulx $MR0, $T0, $T5 # T5:T0 = A3*B0 - xor %rax, %rax - mulx $MR8, $T7, $T6 # T6:T7 = A3*B1 - adcx $T7, $T5 - adox $T0, $T1 - mulx $MR16, $T8, $T7 # T7:T8 = A3*B2 - adcx $T8, $T6 - adox $T5, $T2 - mulx $MR24, $T9, $T8 # T8:T9 = A3*B3 - adcx $T9, $T7 - adcx %rax, $T8 - adox $T6, $T3 - adox $T7, $T4 - adox %rax, $T8 - mov $T1, $D3 # DST3_final - mov $T2, $D4 # DST4_final - mov $T3, $D5 # DST5_final - mov $T4, $D6 # DST6_final - mov $T8, $D7 # DST7_final - -___ - return $body; -} - -# Performs schoolbook multiplication of 64-bit with 256-bit -# number. -sub mul64x256 { - my ($idxM0,$M0,$M1,$T0,$T1,$T2,$T3,$T4,$T5)=@_; - my $body.=<<___; - mov $idxM0($M0), $T5 - - xor $T2, $T2 - mov 0+$M1, %rax - mul $T5 - mov %rax, $T0 # C0 - mov %rdx, $T1 - - xor $T3, $T3 - mov 8+$M1, %rax - mul $T5 - add %rax, $T1 # C1 - adc %rdx, $T2 - - xor $T4, $T4 - mov 16+$M1, %rax - mul $T5 - add %rax, $T2 # C2 - adc %rdx, $T3 - - mov 24+$M1, %rax - mul $T5 - add %rax, $T3 # C3 - adc %rdx, $T4 # C4 -___ - return $body; -} - -# Performs schoolbook multiplication of 64-bit with 256-bit -# number. Uses MULX and ADOX instructions. -sub mulx64x256 { - my ($idxM0,$M0,$M1,$T0,$T1,$T2,$T3,$T4,$T5)=@_; - my $body.=<<___; - xor %rax, %rax - mov $idxM0($M0), %rdx - mulx 0+$M1, $T0, $T1 # T0 <- C0 - mulx 8+$M1, $T4, $T2 - mulx 16+$M1, $T5, $T3 - - adox $T4, $T1 # T1 <- C1 - adox $T5, $T2 # T2 <- C2 - - mulx 24+$M1, $T5, $T4 - adox $T5, $T3 # T3 <- C3 - adox %rax, $T4 # T4 <- C4 -___ - return $body; -} - -# Performs schoolbook multiplication of 128-bit with 256-bit -# number. Destroys RAX and RDX -sub mul128x256 { - my ($idxMA,$MA,$MB,$C0,$C1,$C2,$C3,$C4,$C5,$T0,$T1)=@_; - my ($MA0,$MA8)=map("$idxMA+$_($MA)", (0,8)); - my $body.=<<___; - # A0 x B0 - mov $MA0, $T0 - mov 0+$MB, %rax - mul $T0 - xor $C2, $C2 - mov %rax, $C0 # c0 - mov %rdx, $C1 - - # A0 x B1 - mov 8+$MB, %rax - mul $T0 - xor $C3, $C3 - add %rax, $C1 - adc %rdx, $C2 - - # A1 x B0 - mov $MA8, $T1 - mov 0+$MB, %rax - mul $T1 - add %rax, $C1 - adc %rdx, $C2 - adc \$0x0, $C3 - - # A0 x B2 - xor $C4, $C4 - mov 16+$MB, %rax - mul $T0 - add %rax, $C2 - adc %rdx, $C3 - adc \$0x0, $C4 - - # A1 x B1 - mov 8+$MB, %rax - mul $T1 - add %rax, $C2 # c2 - adc %rdx, $C3 - adc \$0x0, $C4 - - # A0 x B3 - mov 24+$MB, %rax - mul $T0 - xor $C5, $C5 - add %rax, $C3 - adc %rdx, $C4 - adc \$0x0, $C5 - - # A1 x B2 - mov 16+$MB, %rax - mul $T1 - add %rax, $C3 # c3 - adc %rdx, $C4 - adc \$0x0, $C5 - - # A1 x B3 - mov 24+$MB, %rax - mul $T1 - add %rax, $C4 - adc %rdx, $C5 - -___ - return $body; -} - -# Performs schoolbook multiplication of 128-bit with 256-bit -# number. Uses MULX, ADOX, ADCX instruction. -sub mulx128x256 { - my ($idxM0,$M0,$M1,$T0,$T1,$T2,$T3,$T4,$T5,$T6)=@_; - my ($MUL0,$MUL8)=map("$idxM0+$_($M0)", (0,8)); - my $body.=<<___; - xor %rax, %rax - mov $MUL0, %rdx - mulx 0+$M1, $T0, $T1 # T0 <- C0 - mulx 8+$M1, $T4, $T2 - mulx 16+$M1, $T5, $T3 - - adox $T4, $T1 # T1: interm1 - adox $T5, $T2 # T2: interm2 - - mulx 24+$M1, $T5, $T4 - adox $T5, $T3 # T3: interm3 - adox %rax, $T4 # T4: interm4 - - xor %rax, %rax - mov $MUL8, %rdx - mulx 0+$M1, $T5, $T6 - adcx $T5, $T1 # T1 <- C1 - adcx $T6, $T2 - - mulx 8+$M1, $T6, $T5 - adcx $T5, $T3 - adox $T6, $T2 # T2 <- C2 - - mulx 16+$M1, $T6, $T5 - adcx $T5, $T4 - adox $T6, $T3 # T3 <- C3 - - mulx 24+$M1, $T6, $T5 - adcx %rax, $T5 - adox $T6, $T4 # T4 <- C4 - adox %rax, $T5 # T5 <- C5 -___ - return $body; -} - -# Compute z = x + y (mod p). -# Operation: c [rdx] = a [rdi] + b [rsi] -$code.=<<___; -.globl ${PREFIX}_fpadd -.type ${PREFIX}_fpadd,\@function,3 -${PREFIX}_fpadd: -.cfi_startproc - push %r12 -.cfi_adjust_cfa_offset 8 -.cfi_offset r12, -16 - push %r13 -.cfi_adjust_cfa_offset 8 -.cfi_offset r13, -24 - push %r14 -.cfi_adjust_cfa_offset 8 -.cfi_offset r14, -32 - - xor %rax, %rax - - mov 0x0(%rdi), %r8 - add 0x0(%rsi), %r8 - mov 0x8(%rdi), %r9 - adc 0x8(%rsi), %r9 - mov 0x10(%rdi), %r10 - adc 0x10(%rsi), %r10 - mov 0x18(%rdi), %r11 - adc 0x18(%rsi), %r11 - mov 0x20(%rdi), %r12 - adc 0x20(%rsi), %r12 - mov 0x28(%rdi), %r13 - adc 0x28(%rsi), %r13 - mov 0x30(%rdi), %r14 - adc 0x30(%rsi), %r14 - - mov .Lp434x2(%rip), %rcx - sub %rcx, %r8 - mov 0x8+.Lp434x2(%rip), %rcx - sbb %rcx, %r9 - sbb %rcx, %r10 - mov 0x10+.Lp434x2(%rip), %rcx - sbb %rcx, %r11 - mov 0x18+.Lp434x2(%rip), %rcx - sbb %rcx, %r12 - mov 0x20+.Lp434x2(%rip), %rcx - sbb %rcx, %r13 - mov 0x28+.Lp434x2(%rip), %rcx - sbb %rcx, %r14 - - sbb \$0, %rax - - mov .Lp434x2(%rip), %rdi - and %rax, %rdi - mov 0x8+.Lp434x2(%rip), %rsi - and %rax, %rsi - mov 0x10+.Lp434x2(%rip), %rcx - and %rax, %rcx - - add %rdi, %r8 - mov %r8, 0x0(%rdx) - adc %rsi, %r9 - mov %r9, 0x8(%rdx) - adc %rsi, %r10 - mov %r10, 0x10(%rdx) - adc %rcx, %r11 - mov %r11, 0x18(%rdx) - - setc %cl - mov 0x18+.Lp434x2(%rip), %r8 - and %rax, %r8 - mov 0x20+.Lp434x2(%rip), %r9 - and %rax, %r9 - mov 0x28+.Lp434x2(%rip), %r10 - and %rax, %r10 - bt \$0, %rcx - - adc %r8, %r12 - mov %r12, 0x20(%rdx) - adc %r9, %r13 - mov %r13, 0x28(%rdx) - adc %r10, %r14 - mov %r14, 0x30(%rdx) - - pop %r14 -.cfi_adjust_cfa_offset -8 - pop %r13 -.cfi_adjust_cfa_offset -8 - pop %r12 -.cfi_adjust_cfa_offset -8 - ret -.cfi_endproc -___ - -# Loads data to XMM0 and XMM1 and -# conditionaly swaps depending on XMM3 -sub cswap_block16() { - my $idx = shift; - $idx *= 16; - (" - movdqu $idx(%rdi), %xmm0 - movdqu $idx(%rsi), %xmm1 - movdqa %xmm1, %xmm2 - pxor %xmm0, %xmm2 - pand %xmm3, %xmm2 - pxor %xmm2, %xmm0 - pxor %xmm2, %xmm1 - movdqu %xmm0, $idx(%rdi) - movdqu %xmm1, $idx(%rsi) - "); -} - -# Conditionally swaps bits in x and y in constant time. -# mask indicates bits to be swapped (set bits are swapped) -# Operation: [rdi] <-> [rsi] if rdx==1 -sub sike_cswap { - # P[0] with Q[0] - foreach ( 0.. 6){$BLOCKS.=eval "&cswap_block16($_)";} - # P[1] with Q[1] - foreach ( 7..13){$BLOCKS.=eval "&cswap_block16($_)";} - - my $body =<<___; -.globl ${PREFIX}_cswap_asm -.type ${PREFIX}_cswap_asm,\@function,3 -${PREFIX}_cswap_asm: - # Fill XMM3. After this step first half of XMM3 is - # just zeros and second half is whatever in RDX - mov %rdx, %xmm3 - - # Copy lower double word everywhere else. So that - # XMM3=RDX|RDX. As RDX has either all bits set - # or non result will be that XMM3 has also either - # all bits set or non of them. 68 = 01000100b - pshufd \$68, %xmm3, %xmm3 - $BLOCKS - ret -___ - ($body) -} -$code.=&sike_cswap(); - - -# Field subtraction -# Operation: c [rdx] = a [rdi] - b [rsi] -$code.=<<___; -.globl ${PREFIX}_fpsub -.type ${PREFIX}_fpsub,\@function,3 -${PREFIX}_fpsub: -.cfi_startproc - push %r12 -.cfi_adjust_cfa_offset 8 -.cfi_offset r12, -16 - push %r13 -.cfi_adjust_cfa_offset 8 -.cfi_offset r13, -24 - push %r14 -.cfi_adjust_cfa_offset 8 -.cfi_offset r14, -32 - - xor %rax, %rax - - mov 0x0(%rdi), %r8 - sub 0x0(%rsi), %r8 - mov 0x8(%rdi), %r9 - sbb 0x8(%rsi), %r9 - mov 0x10(%rdi), %r10 - sbb 0x10(%rsi), %r10 - mov 0x18(%rdi), %r11 - sbb 0x18(%rsi), %r11 - mov 0x20(%rdi), %r12 - sbb 0x20(%rsi), %r12 - mov 0x28(%rdi), %r13 - sbb 0x28(%rsi), %r13 - mov 0x30(%rdi), %r14 - sbb 0x30(%rsi), %r14 - - sbb \$0x0, %rax - - mov .Lp434x2(%rip), %rdi - and %rax, %rdi - mov 0x08+.Lp434x2(%rip), %rsi - and %rax, %rsi - mov 0x10+.Lp434x2(%rip), %rcx - and %rax, %rcx - - add %rdi, %r8 - mov %r8, 0x0(%rdx) - adc %rsi, %r9 - mov %r9, 0x8(%rdx) - adc %rsi, %r10 - mov %r10, 0x10(%rdx) - adc %rcx, %r11 - mov %r11, 0x18(%rdx) - - setc %cl - mov 0x18+.Lp434x2(%rip), %r8 - and %rax, %r8 - mov 0x20+.Lp434x2(%rip), %r9 - and %rax, %r9 - mov 0x28+.Lp434x2(%rip), %r10 - and %rax, %r10 - bt \$0x0, %rcx - - adc %r8, %r12 - adc %r9, %r13 - adc %r10, %r14 - mov %r12, 0x20(%rdx) - mov %r13, 0x28(%rdx) - mov %r14, 0x30(%rdx) - - pop %r14 -.cfi_adjust_cfa_offset -8 - pop %r13 -.cfi_adjust_cfa_offset -8 - pop %r12 -.cfi_adjust_cfa_offset -8 - ret -.cfi_endproc -___ - -# 434-bit multiprecision addition -# Operation: c [rdx] = a [rdi] + b [rsi] -$code.=<<___; -.globl ${PREFIX}_mpadd_asm -.type ${PREFIX}_mpadd_asm,\@function,3 -${PREFIX}_mpadd_asm: -.cfi_startproc - mov 0x0(%rdi), %r8; - mov 0x8(%rdi), %r9 - mov 0x10(%rdi), %r10 - mov 0x18(%rdi), %r11 - mov 0x20(%rdi), %rcx - add 0x0(%rsi), %r8 - adc 0x8(%rsi), %r9 - adc 0x10(%rsi), %r10 - adc 0x18(%rsi), %r11 - adc 0x20(%rsi), %rcx - mov %r8, 0x0(%rdx) - mov %r9, 0x8(%rdx) - mov %r10, 0x10(%rdx) - mov %r11, 0x18(%rdx) - mov %rcx, 0x20(%rdx) - - mov 0x28(%rdi), %r8 - mov 0x30(%rdi), %r9 - adc 0x28(%rsi), %r8 - adc 0x30(%rsi), %r9 - mov %r8, 0x28(%rdx) - mov %r9, 0x30(%rdx) - ret -.cfi_endproc -___ - -# 2x434-bit multiprecision subtraction -# Operation: c [rdx] = a [rdi] - b [rsi]. -# Returns borrow mask -$code.=<<___; -.globl ${PREFIX}_mpsubx2_asm -.type ${PREFIX}_mpsubx2_asm,\@function,3 -${PREFIX}_mpsubx2_asm: -.cfi_startproc - xor %rax, %rax - - mov 0x0(%rdi), %r8 - mov 0x8(%rdi), %r9 - mov 0x10(%rdi), %r10 - mov 0x18(%rdi), %r11 - mov 0x20(%rdi), %rcx - sub 0x0(%rsi), %r8 - sbb 0x8(%rsi), %r9 - sbb 0x10(%rsi), %r10 - sbb 0x18(%rsi), %r11 - sbb 0x20(%rsi), %rcx - mov %r8, 0x0(%rdx) - mov %r9, 0x8(%rdx) - mov %r10, 0x10(%rdx) - mov %r11, 0x18(%rdx) - mov %rcx, 0x20(%rdx) - - mov 0x28(%rdi), %r8 - mov 0x30(%rdi), %r9 - mov 0x38(%rdi), %r10 - mov 0x40(%rdi), %r11 - mov 0x48(%rdi), %rcx - sbb 0x28(%rsi), %r8 - sbb 0x30(%rsi), %r9 - sbb 0x38(%rsi), %r10 - sbb 0x40(%rsi), %r11 - sbb 0x48(%rsi), %rcx - mov %r8, 0x28(%rdx) - mov %r9, 0x30(%rdx) - mov %r10, 0x38(%rdx) - mov %r11, 0x40(%rdx) - mov %rcx, 0x48(%rdx) - - mov 0x50(%rdi), %r8 - mov 0x58(%rdi), %r9 - mov 0x60(%rdi), %r10 - mov 0x68(%rdi), %r11 - sbb 0x50(%rsi), %r8 - sbb 0x58(%rsi), %r9 - sbb 0x60(%rsi), %r10 - sbb 0x68(%rsi), %r11 - sbb \$0x0, %rax - mov %r8, 0x50(%rdx) - mov %r9, 0x58(%rdx) - mov %r10, 0x60(%rdx) - mov %r11, 0x68(%rdx) - ret -.cfi_endproc -___ - - -# Double 2x434-bit multiprecision subtraction -# Operation: c [rdx] = c [rdx] - a [rdi] - b [rsi] -$code.=<<___; -.globl ${PREFIX}_mpdblsubx2_asm -.type ${PREFIX}_mpdblsubx2_asm,\@function,3 -${PREFIX}_mpdblsubx2_asm: -.cfi_startproc - push %r12 -.cfi_adjust_cfa_offset 8 -.cfi_offset r12, -16 - push %r13 -.cfi_adjust_cfa_offset 8 -.cfi_offset r13, -24 - - xor %rax, %rax - - # ci:low = c:low - a:low - mov 0x0(%rdx), %r8 - mov 0x8(%rdx), %r9 - mov 0x10(%rdx), %r10 - mov 0x18(%rdx), %r11 - mov 0x20(%rdx), %r12 - mov 0x28(%rdx), %r13 - mov 0x30(%rdx), %rcx - sub 0x0(%rdi), %r8 - sbb 0x8(%rdi), %r9 - sbb 0x10(%rdi), %r10 - sbb 0x18(%rdi), %r11 - sbb 0x20(%rdi), %r12 - sbb 0x28(%rdi), %r13 - sbb 0x30(%rdi), %rcx - adc \$0x0, %rax - - # c:low = ci:low - b:low - sub 0x0(%rsi), %r8 - sbb 0x8(%rsi), %r9 - sbb 0x10(%rsi), %r10 - sbb 0x18(%rsi), %r11 - sbb 0x20(%rsi), %r12 - sbb 0x28(%rsi), %r13 - sbb 0x30(%rsi), %rcx - adc \$0x0, %rax - - # store c:low - mov %r8, 0x0(%rdx) - mov %r9, 0x8(%rdx) - mov %r10, 0x10(%rdx) - mov %r11, 0x18(%rdx) - mov %r12, 0x20(%rdx) - mov %r13, 0x28(%rdx) - mov %rcx, 0x30(%rdx) - - # ci:high = c:high - a:high - mov 0x38(%rdx), %r8 - mov 0x40(%rdx), %r9 - mov 0x48(%rdx), %r10 - mov 0x50(%rdx), %r11 - mov 0x58(%rdx), %r12 - mov 0x60(%rdx), %r13 - mov 0x68(%rdx), %rcx - - sub %rax, %r8 - sbb 0x38(%rdi), %r8 - sbb 0x40(%rdi), %r9 - sbb 0x48(%rdi), %r10 - sbb 0x50(%rdi), %r11 - sbb 0x58(%rdi), %r12 - sbb 0x60(%rdi), %r13 - sbb 0x68(%rdi), %rcx - - # c:high = ci:high - b:high - sub 0x38(%rsi), %r8 - sbb 0x40(%rsi), %r9 - sbb 0x48(%rsi), %r10 - sbb 0x50(%rsi), %r11 - sbb 0x58(%rsi), %r12 - sbb 0x60(%rsi), %r13 - sbb 0x68(%rsi), %rcx - - # store c:high - mov %r8, 0x38(%rdx) - mov %r9, 0x40(%rdx) - mov %r10, 0x48(%rdx) - mov %r11, 0x50(%rdx) - mov %r12, 0x58(%rdx) - mov %r13, 0x60(%rdx) - mov %rcx, 0x68(%rdx) - - pop %r13 -.cfi_adjust_cfa_offset -8 - pop %r12 -.cfi_adjust_cfa_offset -8 - ret -.cfi_endproc - -___ - -sub redc_common { - my ($mul01, $mul23, $mul45, $mul67)=@_; - my $body=<<___; - $mul01 - xor %rcx, %rcx - add 0x18(%rdi), %r8 - adc 0x20(%rdi), %r9 - adc 0x28(%rdi), %r10 - adc 0x30(%rdi), %r11 - adc 0x38(%rdi), %r12 - adc 0x40(%rdi), %r13 - adc 0x48(%rdi), %rcx - mov %r8, 0x18(%rdi) - mov %r9, 0x20(%rdi) - mov %r10, 0x28(%rdi) - mov %r11, 0x30(%rdi) - mov %r12, 0x38(%rdi) - mov %r13, 0x40(%rdi) - mov %rcx, 0x48(%rdi) - mov 0x50(%rdi), %r8 - mov 0x58(%rdi), %r9 - mov 0x60(%rdi), %r10 - mov 0x68(%rdi), %r11 - adc \$0x0, %r8 - adc \$0x0, %r9 - adc \$0x0, %r10 - adc \$0x0, %r11 - mov %r8, 0x50(%rdi) - mov %r9, 0x58(%rdi) - mov %r10, 0x60(%rdi) - mov %r11, 0x68(%rdi) - - $mul23 - xor %rcx, %rcx - add 0x28(%rdi), %r8 - adc 0x30(%rdi), %r9 - adc 0x38(%rdi), %r10 - adc 0x40(%rdi), %r11 - adc 0x48(%rdi), %r12 - adc 0x50(%rdi), %r13 - adc 0x58(%rdi), %rcx - mov %r8, 0x28(%rdi) - mov %r9, 0x30(%rdi) - mov %r10, 0x38(%rdi) - mov %r11, 0x40(%rdi) - mov %r12, 0x48(%rdi) - mov %r13, 0x50(%rdi) - mov %rcx, 0x58(%rdi) - mov 0x60(%rdi), %r8 - mov 0x68(%rdi), %r9 - adc \$0x0, %r8 - adc \$0x0, %r9 - mov %r8, 0x60(%rdi) - mov %r9, 0x68(%rdi) - - $mul45 - xor %rcx, %rcx - add 0x38(%rdi), %r8 - adc 0x40(%rdi), %r9 - adc 0x48(%rdi), %r10 - adc 0x50(%rdi), %r11 - adc 0x58(%rdi), %r12 - adc 0x60(%rdi), %r13 - adc 0x68(%rdi), %rcx - mov %r8, 0x0(%rsi) # C0 - mov %r9, 0x8(%rsi) # C1 - mov %r10, 0x48(%rdi) - mov %r11, 0x50(%rdi) - mov %r12, 0x58(%rdi) - mov %r13, 0x60(%rdi) - mov %rcx, 0x68(%rdi) - - $mul67 - add 0x48(%rdi), %r8 - adc 0x50(%rdi), %r9 - adc 0x58(%rdi), %r10 - adc 0x60(%rdi), %r11 - adc 0x68(%rdi), %r12 - mov %r8, 0x10(%rsi) # C2 - mov %r9, 0x18(%rsi) # C3 - mov %r10, 0x20(%rsi) # C4 - mov %r11, 0x28(%rsi) # C5 - mov %r12, 0x30(%rsi) # C6 -___ - return $body; -} - -# Optimized Montgomery reduction for CPUs, based on method described -# in Faz-Hernandez et al. https://eprint.iacr.org/2017/1015. -# Operation: c [rsi] = a [rdi] -# NOTE: a=c is not allowed -sub sike_rdc { - my $jump_redc_bdw=&alt_impl(".Lrdc_bdw") if ($bmi2_adx); - # a[0-1] x .Lp434p1 --> result: r8:r13 - my $mulx1=&mulx128x256( 0,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..13)),"%rcx"); - # a[2-3] x .Lp434p1 --> result: r8:r13 - my $mulx2=&mulx128x256(16,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..13)),"%rcx"); - # a[4-5] x .Lp434p1 --> result: r8:r13 - my $mulx3=&mulx128x256(32,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..13)),"%rcx"); - # a[6-7] x .Lp434p1 --> result: r8:r13 - my $mulx4=&mulx64x256( 48,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..13))); - - # a[0-1] x .Lp434p1 --> result: r8:r13 - my $mul1=&mul128x256( 0,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..14)),"%rcx"); - # a[2-3] x .Lp434p1 --> result: r8:r13 - my $mul2=&mul128x256(16,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..14)),"%rcx"); - # a[4-5] x .Lp434p1 --> result: r8:r13 - my $mul3=&mul128x256(32,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..14)),"%rcx"); - # a[6-7] x .Lp434p1 --> result: r8:r13 - my $mul4=&mul64x256( 48,"%rdi",".Lp434p1(%rip)",map("%r$_",(8..13))); - - my $redc_mul=&redc_common($mul1, $mul2, $mul3, $mul4); - my $redc_bdw=&redc_common($mulx1, $mulx2, $mulx3, $mulx4) if ($bmi2_adx); - - # REDC for Broadwell CPUs - my $code=<<___; - .Lrdc_bdw: - .cfi_startproc - # sike_fprdc has already pushed r12--15 by this point. - .cfi_adjust_cfa_offset 32 - .cfi_offset r12, -16 - .cfi_offset r13, -24 - .cfi_offset r14, -32 - .cfi_offset r15, -40 - - $redc_bdw - - pop %r15 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r15 - pop %r14 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r14 - pop %r13 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r13 - pop %r12 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r12 - ret - .cfi_endproc -___ - - # REDC for CPUs older than Broadwell - $code.=<<___; - .globl ${PREFIX}_fprdc - .type ${PREFIX}_fprdc,\@function,3 - ${PREFIX}_fprdc: - .cfi_startproc - push %r12 - .cfi_adjust_cfa_offset 8 - .cfi_offset r12, -16 - push %r13 - .cfi_adjust_cfa_offset 8 - .cfi_offset r13, -24 - push %r14 - .cfi_adjust_cfa_offset 8 - .cfi_offset r14, -32 - push %r15 - .cfi_adjust_cfa_offset 8 - .cfi_offset r15, -40 - - # Jump to optimized implementation if - # CPU supports ADCX/ADOX/MULX - $jump_redc_bdw - # Otherwise use generic implementation - $redc_mul - - pop %r15 - .cfi_adjust_cfa_offset -8 - pop %r14 - .cfi_adjust_cfa_offset -8 - pop %r13 - .cfi_adjust_cfa_offset -8 - pop %r12 - .cfi_adjust_cfa_offset -8 - ret - .cfi_endproc -___ - return $code; -} -$code.=&sike_rdc(); - -# 434-bit multiplication using Karatsuba (one level), -# schoolbook (one level). Uses MULX/ADOX/ADCX instructions -# available on Broadwell micro-architectures and newer. -sub mul_bdw { - # [rsp] <- (AH+AL) x (BH+BL) - my $mul256_low=&mul256(0,"%rsp",32,"%rsp",0,"%rsp",map("%r$_",(8..15)),"%rbx","%rbp"); - # [rcx] <- AL x BL - my $mul256_albl=&mul256(0,"%rdi",0,"%rsi",0,"%rcx",map("%r$_",(8..15)),"%rbx","%rbp"); - # [rcx+64] <- AH x BH - my $mul192_ahbh=&mul192(32,"%rdi",32,"%rsi",64,"%rcx",map("%r$_",(8..14))); - - $body=<<___; - - mov %rdx, %rcx - xor %rax, %rax - - # r8-r11 <- AH + AL, rax <- mask - mov 0x0(%rdi), %r8 - mov 0x8(%rdi), %r9 - mov 0x10(%rdi), %r10 - mov 0x18(%rdi), %r11 - - push %rbx - .cfi_adjust_cfa_offset 8 - .cfi_offset rbx, -48 - push %rbp - .cfi_offset rbp, -56 - .cfi_adjust_cfa_offset 8 - sub \$96, %rsp - .cfi_adjust_cfa_offset 96 - - add 0x20(%rdi), %r8 - adc 0x28(%rdi), %r9 - adc 0x30(%rdi), %r10 - adc \$0x0, %r11 - sbb \$0x0, %rax - mov %r8, 0x0(%rsp) - mov %r9, 0x8(%rsp) - mov %r10, 0x10(%rsp) - mov %r11, 0x18(%rsp) - - # r12-r15 <- BH + BL, rbx <- mask - xor %rbx, %rbx - mov 0x0(%rsi), %r12 - mov 0x8(%rsi), %r13 - mov 0x10(%rsi), %r14 - mov 0x18(%rsi), %r15 - add 0x20(%rsi), %r12 - adc 0x28(%rsi), %r13 - adc 0x30(%rsi), %r14 - adc \$0x0, %r15 - sbb \$0x0, %rbx - mov %r12, 0x20(%rsp) - mov %r13, 0x28(%rsp) - mov %r14, 0x30(%rsp) - mov %r15, 0x38(%rsp) - - # r12-r15 <- masked (BH + BL) - and %rax, %r12 - and %rax, %r13 - and %rax, %r14 - and %rax, %r15 - - # r8-r11 <- masked (AH + AL) - and %rbx, %r8 - and %rbx, %r9 - and %rbx, %r10 - and %rbx, %r11 - - # r8-r11 <- masked (AH + AL) + masked (BH + BL) - add %r12, %r8 - adc %r13, %r9 - adc %r14, %r10 - adc %r15, %r11 - mov %r8, 0x40(%rsp) - mov %r9, 0x48(%rsp) - mov %r10, 0x50(%rsp) - mov %r11, 0x58(%rsp) - - # [rsp] <- CM = (AH+AL) x (BH+BL) - $mul256_low - # [rcx] <- CL = AL x BL (Result c0-c3) - $mul256_albl - # [rcx+64] <- CH = AH x BH - $mul192_ahbh - - # r8-r11 <- (AH+AL) x (BH+BL), final step - mov 0x40(%rsp), %r8 - mov 0x48(%rsp), %r9 - mov 0x50(%rsp), %r10 - mov 0x58(%rsp), %r11 - - mov 0x20(%rsp), %rax - add %rax, %r8 - mov 0x28(%rsp), %rax - adc %rax, %r9 - mov 0x30(%rsp), %rax - adc %rax, %r10 - mov 0x38(%rsp), %rax - adc %rax, %r11 - - # [rsp], x3-x5 <- (AH+AL) x (BH+BL) - ALxBL - mov 0x0(%rsp), %r12 - mov 0x8(%rsp), %r13 - mov 0x10(%rsp), %r14 - mov 0x18(%rsp), %r15 - sub 0x0(%rcx), %r12 - sbb 0x8(%rcx), %r13 - sbb 0x10(%rcx), %r14 - sbb 0x18(%rcx), %r15 - sbb 0x20(%rcx), %r8 - sbb 0x28(%rcx), %r9 - sbb 0x30(%rcx), %r10 - sbb 0x38(%rcx), %r11 - - # r8-r15 <- (AH+AL) x (BH+BL) - ALxBL - AHxBH - sub 0x40(%rcx), %r12 - sbb 0x48(%rcx), %r13 - sbb 0x50(%rcx), %r14 - sbb 0x58(%rcx), %r15 - sbb 0x60(%rcx), %r8 - sbb 0x68(%rcx), %r9 - sbb \$0x0, %r10 - sbb \$0x0, %r11 - - add 0x20(%rcx), %r12 - mov %r12, 0x20(%rcx) # Result C4-C7 - adc 0x28(%rcx), %r13 - mov %r13, 0x28(%rcx) - adc 0x30(%rcx), %r14 - mov %r14, 0x30(%rcx) - adc 0x38(%rcx), %r15 - mov %r15, 0x38(%rcx) - adc 0x40(%rcx), %r8 - mov %r8, 0x40(%rcx) # Result C8-C15 - adc 0x48(%rcx), %r9 - mov %r9, 0x48(%rcx) - adc 0x50(%rcx), %r10 - mov %r10, 0x50(%rcx) - adc 0x58(%rcx), %r11 - mov %r11, 0x58(%rcx) - mov 0x60(%rcx), %r12 - adc \$0x0, %r12 - mov %r12, 0x60(%rcx) - mov 0x68(%rcx), %r13 - adc \$0x0, %r13 - mov %r13, 0x68(%rcx) - - add \$96, %rsp - .cfi_adjust_cfa_offset -96 - pop %rbp - .cfi_adjust_cfa_offset -8 - .cfi_same_value rbp - pop %rbx - .cfi_adjust_cfa_offset -8 - .cfi_same_value rbx -___ - return $body; -} - -# 434-bit multiplication using Karatsuba (one level), -# schoolbook (one level). -sub mul { - my $code=<<___; - mov %rdx, %rcx - - sub \$112, %rsp # Allocating space in stack - .cfi_adjust_cfa_offset 112 - - # rcx[0-3] <- AH+AL - xor %rax, %rax - mov 0x20(%rdi), %r8 - mov 0x28(%rdi), %r9 - mov 0x30(%rdi), %r10 - xor %r11, %r11 - add 0x0(%rdi), %r8 - adc 0x8(%rdi), %r9 - adc 0x10(%rdi), %r10 - adc 0x18(%rdi), %r11 - # store AH+AL mask - sbb \$0, %rax - mov %rax, 0x40(%rsp) - # store AH+AL in 0-0x18(rcx) - mov %r8, 0x0(%rcx) - mov %r9, 0x8(%rcx) - mov %r10, 0x10(%rcx) - mov %r11, 0x18(%rcx) - - # r12-r15 <- BH+BL - xor %rdx, %rdx - mov 0x20(%rsi), %r12 - mov 0x28(%rsi), %r13 - mov 0x30(%rsi), %r14 - xor %r15, %r15 - add 0x0(%rsi), %r12 - adc 0x8(%rsi), %r13 - adc 0x10(%rsi), %r14 - adc 0x18(%rsi), %r15 - sbb \$0x0, %rdx - # store BH+BL mask - mov %rdx, 0x48(%rsp) - - # (rsp[0-0x38]) <- (AH+AL)*(BH+BL) - mov (%rcx), %rax - mul %r12 - mov %rax, (%rsp) # c0 - mov %rdx, %r8 - - xor %r9, %r9 - mov (%rcx), %rax - mul %r13 - add %rax, %r8 - adc %rdx, %r9 - - xor %r10, %r10 - mov 0x8(%rcx), %rax - mul %r12 - add %rax, %r8 - mov %r8, 0x8(%rsp) # c1 - adc %rdx, %r9 - adc \$0x0,%r10 - - xor %r8, %r8 - mov (%rcx), %rax - mul %r14 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x10(%rcx), %rax - mul %r12 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x8(%rcx), %rax - mul %r13 - add %rax, %r9 - mov %r9, 0x10(%rsp) # c2 - adc %rdx, %r10 - adc \$0x0, %r8 - - xor %r9, %r9 - mov (%rcx),%rax - mul %r15 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r9 - - mov 0x18(%rcx), %rax - mul %r12 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r9 - - mov 0x8(%rcx), %rax - mul %r14 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r9 - - mov 0x10(%rcx), %rax - mul %r13 - add %rax, %r10 - mov %r10, 0x18(%rsp) # c3 - adc %rdx, %r8 - adc \$0x0, %r9 - - xor %r10, %r10 - mov 0x8(%rcx), %rax - mul %r15 - add %rax, %r8 - adc %rdx, %r9 - adc \$0x0,%r10 - - mov 0x18(%rcx), %rax - mul %r13 - add %rax, %r8 - adc %rdx, %r9 - adc \$0x0,%r10 - - mov 0x10(%rcx), %rax - mul %r14 - add %rax, %r8 # c4 - mov %r8, 0x20(%rsp) - adc %rdx, %r9 - adc \$0x0,%r10 - - xor %r11, %r11 - mov 0x10(%rcx), %rax - mul %r15 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r11 - - mov 0x18(%rcx), %rax - mul %r14 - add %rax, %r9 # c5 - mov %r9, 0x28(%rsp) - adc %rdx, %r10 - adc \$0x0,%r11 - - mov 0x18(%rcx), %rax - mul %r15 - add %rax, %r10 # c6 - mov %r10, 0x30(%rsp) - adc %rdx, %r11 # c7 - mov %r11, 0x38(%rsp) - - # r12-r15 <- masked (BH + BL) - mov 0x40(%rsp), %rax - and %rax, %r12 - and %rax, %r13 - and %rax, %r14 - and %rax, %r15 - - # r8-r11 <- masked (AH + AL) - mov 0x48(%rsp),%rax - mov 0x00(rcx), %r8 - and %rax, %r8 - mov 0x08(rcx), %r9 - and %rax, %r9 - mov 0x10(rcx), %r10 - and %rax, %r10 - mov 0x18(rcx), %r11 - and %rax, %r11 - - # r12-r15 <- masked (AH + AL) + masked (BH + BL) - add %r8, %r12 - adc %r9, %r13 - adc %r10, %r14 - adc %r11, %r15 - - # rsp[0x20-0x38] <- (AH+AL) x (BH+BL) high - mov 0x20(%rsp), %rax - add %rax, %r12 - mov 0x28(%rsp), %rax - adc %rax, %r13 - mov 0x30(%rsp), %rax - adc %rax, %r14 - mov 0x38(%rsp), %rax - adc %rax, %r15 - mov %r12, 0x50(%rsp) - mov %r13, 0x58(%rsp) - mov %r14, 0x60(%rsp) - mov %r15, 0x68(%rsp) - - # [rcx] <- CL = AL x BL - mov (%rdi), %r11 - mov (%rsi), %rax - mul %r11 - xor %r9, %r9 - mov %rax, (%rcx) # c0 - mov %rdx, %r8 - - mov 0x10(%rdi), %r14 - mov 0x8(%rsi), %rax - mul %r11 - xor %r10, %r10 - add %rax, %r8 - adc %rdx, %r9 - - mov 0x8(%rdi), %r12 - mov (%rsi), %rax - mul %r12 - add %rax, %r8 - mov %r8, 0x8(%rcx) # c1 - adc %rdx, %r9 - adc \$0x0,%r10 - - xor %r8, %r8 - mov 0x10(%rsi), %rax - mul %r11 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov (%rsi),%r13 - mov %r14, %rax - mul %r13 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x8(%rsi), %rax - mul %r12 - add %rax, %r9 - mov %r9, 0x10(%rcx) # c2 - adc %rdx, %r10 - adc \$0x0,%r8 - - xor %r9, %r9 - mov 0x18(%rsi), %rax - mul %r11 - mov 0x18(%rdi), %r15 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r9 - - mov %r15, %rax - mul %r13 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r9 - - mov 0x10(%rsi), %rax - mul %r12 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r9 - - mov 0x8(%rsi), %rax - mul %r14 - add %rax, %r10 - mov %r10, 0x18(%rcx) # c3 - adc %rdx, %r8 - adc \$0x0,%r9 - - xor %r10, %r10 - mov 0x18(%rsi), %rax - mul %r12 - add %rax, %r8 - adc %rdx, %r9 - adc \$0x0,%r10 - - mov 0x8(%rsi), %rax - mul %r15 - add %rax, %r8 - adc %rdx, %r9 - adc \$0x0,%r10 - - mov 0x10(%rsi), %rax - mul %r14 - add %rax, %r8 - mov %r8, 0x20(%rcx) # c4 - adc %rdx, %r9 - adc \$0x0,%r10 - - xor %r8, %r8 - mov 0x18(%rsi), %rax - mul %r14 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x10(%rsi), %rax - mul %r15 - add %rax, %r9 - mov %r9, 0x28(%rcx) # c5 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x18(%rsi), %rax - mul %r15 - add %rax, %r10 - mov %r10, 0x30(%rcx) # c6 - adc %rdx, %r8 - mov %r8, 0x38(%rcx) # c7 - - # rcx[0x40-0x68] <- AH*BH - # multiplies 2 192-bit numbers A,B - mov 0x20(%rdi), %r11 - mov 0x20(%rsi), %rax - mul %r11 - xor %r9, %r9 - mov %rax, 0x40(%rcx) # c0 - mov %rdx, %r8 - - mov 0x30(%rdi), %r14 - mov 0x28(%rsi), %rax - mul %r11 - xor %r10, %r10 - add %rax, %r8 - adc %rdx, %r9 - - mov 0x28(%rdi), %r12 - mov 0x20(%rsi), %rax - mul %r12 - add %rax, %r8 - mov %r8, 0x48(%rcx) # c1 - adc %rdx, %r9 - adc \$0x0,%r10 - - xor %r8, %r8 - mov 0x30(%rsi), %rax - mul %r11 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x20(%rsi), %r13 - mov %r14, %rax - mul %r13 - add %rax, %r9 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x28(%rsi), %rax - mul %r12 - add %rax, %r9 - mov %r9, 0x50(%rcx) # c2 - adc %rdx, %r10 - adc \$0x0,%r8 - - mov 0x30(%rsi), %rax - mul %r12 - xor %r12, %r12 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r12 - - mov 0x28(%rsi), %rax - mul %r14 - add %rax, %r10 - adc %rdx, %r8 - adc \$0x0,%r12 - mov %r10, 0x58(%rcx) # c3 - - mov 0x30(%rsi), %rax - mul %r14 - add %rax, %r8 - adc \$0x0,%r12 - mov %r8, 0x60(%rcx) # c4 - - add %r12, %rdx # c5 - - # [r8-r15] <- (AH+AL)x(BH+BL) - ALxBL - mov 0x0(%rsp), %r8 - sub 0x0(%rcx), %r8 - mov 0x8(%rsp), %r9 - sbb 0x8(%rcx), %r9 - mov 0x10(%rsp), %r10 - sbb 0x10(%rcx), %r10 - mov 0x18(%rsp), %r11 - sbb 0x18(%rcx), %r11 - mov 0x50(%rsp), %r12 - sbb 0x20(%rcx), %r12 - mov 0x58(%rsp), %r13 - sbb 0x28(%rcx), %r13 - mov 0x60(%rsp), %r14 - sbb 0x30(%rcx), %r14 - mov 0x68(%rsp), %r15 - sbb 0x38(%rcx), %r15 - - # [r8-r15] <- (AH+AL) x (BH+BL) - ALxBL - AHxBH - mov 0x40(%rcx), %rax - sub %rax, %r8 - mov 0x48(%rcx), %rax - sbb %rax, %r9 - mov 0x50(%rcx), %rax - sbb %rax, %r10 - mov 0x58(%rcx), %rax - sbb %rax, %r11 - mov 0x60(%rcx), %rax - sbb %rax, %r12 - sbb %rdx, %r13 - sbb \$0x0,%r14 - sbb \$0x0,%r15 - - # Final result - add 0x20(%rcx), %r8 - mov %r8, 0x20(%rcx) # Result C4-C7 - adc 0x28(%rcx), %r9 - mov %r9, 0x28(%rcx) - adc 0x30(%rcx), %r10 - mov %r10, 0x30(%rcx) - adc 0x38(%rcx), %r11 - mov %r11, 0x38(%rcx) - adc 0x40(%rcx), %r12 - mov %r12, 0x40(%rcx) # Result C8-C13 - adc 0x48(%rcx), %r13 - mov %r13, 0x48(%rcx) - adc 0x50(%rcx), %r14 - mov %r14, 0x50(%rcx) - adc 0x58(%rcx), %r15 - mov %r15, 0x58(%rcx) - mov 0x60(%rcx), %r12 - adc \$0x0, %r12 - mov %r12, 0x60(%rcx) - adc \$0x0, %rdx - mov %rdx, 0x68(%rcx) - - add \$112, %rsp # Restoring space in stack - .cfi_adjust_cfa_offset -112 -___ - - return $code; -} - -# Integer multiplication based on Karatsuba method -# Operation: c [rdx] = a [rdi] * b [rsi] -# NOTE: a=c or b=c are not allowed -sub sike_mul { - my $jump_mul_bdw=&alt_impl(".Lmul_bdw") if ($bmi2_adx); - # MUL for Broadwell CPUs - my $mul_bdw=&mul_bdw() if ($bmi2_adx); - # MUL for CPUs older than Broadwell - my $mul=&mul(); - - my $body=<<___; - .Lmul_bdw: - .cfi_startproc - # sike_mpmul has already pushed r12--15 by this point. - .cfi_adjust_cfa_offset 32 - .cfi_offset r12, -16 - .cfi_offset r13, -24 - .cfi_offset r14, -32 - .cfi_offset r15, -40 - - $mul_bdw - - pop %r15 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r15 - pop %r14 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r14 - pop %r13 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r13 - pop %r12 - .cfi_adjust_cfa_offset -8 - .cfi_same_value r12 - ret - .cfi_endproc - - .globl ${PREFIX}_mpmul - .type ${PREFIX}_mpmul,\@function,3 - ${PREFIX}_mpmul: - .cfi_startproc - push %r12 - .cfi_adjust_cfa_offset 8 - .cfi_offset r12, -16 - push %r13 - .cfi_adjust_cfa_offset 8 - .cfi_offset r13, -24 - push %r14 - .cfi_adjust_cfa_offset 8 - .cfi_offset r14, -32 - push %r15 - .cfi_adjust_cfa_offset 8 - .cfi_offset r15, -40 - - # Jump to optimized implementation if - # CPU supports ADCX/ADOX/MULX - $jump_mul_bdw - # Otherwise use generic implementation - $mul - - pop %r15 - .cfi_adjust_cfa_offset -8 - pop %r14 - .cfi_adjust_cfa_offset -8 - pop %r13 - .cfi_adjust_cfa_offset -8 - pop %r12 - .cfi_adjust_cfa_offset -8 - ret - .cfi_endproc - -___ - return $body; -} - -$code.=&sike_mul(); - -foreach (split("\n",$code)) { - s/\`([^\`]*)\`/eval($1)/ge; - print $_,"\n"; -} - -close STDOUT; diff --git a/third_party/sike/asm/fp_generic.c b/third_party/sike/asm/fp_generic.c deleted file mode 100644 index 991ad1e175..0000000000 --- a/third_party/sike/asm/fp_generic.c +++ /dev/null @@ -1,181 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: portable modular arithmetic for P503 -*********************************************************************************************/ - -#include - -#if defined(OPENSSL_NO_ASM) || \ - (!defined(OPENSSL_X86_64) && !defined(OPENSSL_AARCH64)) - -#include "../utils.h" -#include "../fpx.h" - -// Global constants -extern const struct params_t sike_params; - -static void digit_x_digit(const crypto_word_t a, const crypto_word_t b, crypto_word_t* c) -{ // Digit multiplication, digit * digit -> 2-digit result - crypto_word_t al, ah, bl, bh, temp; - crypto_word_t albl, albh, ahbl, ahbh, res1, res2, res3, carry; - crypto_word_t mask_low = (crypto_word_t)(-1) >> (sizeof(crypto_word_t)*4); - crypto_word_t mask_high = (crypto_word_t)(-1) << (sizeof(crypto_word_t)*4); - - al = a & mask_low; // Low part - ah = a >> (sizeof(crypto_word_t) * 4); // High part - bl = b & mask_low; - bh = b >> (sizeof(crypto_word_t) * 4); - - albl = al*bl; - albh = al*bh; - ahbl = ah*bl; - ahbh = ah*bh; - c[0] = albl & mask_low; // C00 - - res1 = albl >> (sizeof(crypto_word_t) * 4); - res2 = ahbl & mask_low; - res3 = albh & mask_low; - temp = res1 + res2 + res3; - carry = temp >> (sizeof(crypto_word_t) * 4); - c[0] ^= temp << (sizeof(crypto_word_t) * 4); // C01 - - res1 = ahbl >> (sizeof(crypto_word_t) * 4); - res2 = albh >> (sizeof(crypto_word_t) * 4); - res3 = ahbh & mask_low; - temp = res1 + res2 + res3 + carry; - c[1] = temp & mask_low; // C10 - carry = temp & mask_high; - c[1] ^= (ahbh & mask_high) + carry; // C11 -} - -void sike_fpadd(const felm_t a, const felm_t b, felm_t c) -{ // Modular addition, c = a+b mod p434. - // Inputs: a, b in [0, 2*p434-1] - // Output: c in [0, 2*p434-1] - unsigned int i, carry = 0; - crypto_word_t mask; - - for (i = 0; i < NWORDS_FIELD; i++) { - ADDC(carry, a[i], b[i], carry, c[i]); - } - - carry = 0; - for (i = 0; i < NWORDS_FIELD; i++) { - SUBC(carry, c[i], sike_params.prime_x2[i], carry, c[i]); - } - mask = 0 - (crypto_word_t)carry; - - carry = 0; - for (i = 0; i < NWORDS_FIELD; i++) { - ADDC(carry, c[i], sike_params.prime_x2[i] & mask, carry, c[i]); - } -} - -void sike_fpsub(const felm_t a, const felm_t b, felm_t c) -{ // Modular subtraction, c = a-b mod p434. - // Inputs: a, b in [0, 2*p434-1] - // Output: c in [0, 2*p434-1] - unsigned int i, borrow = 0; - crypto_word_t mask; - - for (i = 0; i < NWORDS_FIELD; i++) { - SUBC(borrow, a[i], b[i], borrow, c[i]); - } - mask = 0 - (crypto_word_t)borrow; - - borrow = 0; - for (i = 0; i < NWORDS_FIELD; i++) { - ADDC(borrow, c[i], sike_params.prime_x2[i] & mask, borrow, c[i]); - } -} - -void sike_mpmul(const felm_t a, const felm_t b, dfelm_t c) -{ // Multiprecision comba multiply, c = a*b, where lng(a) = lng(b) = NWORDS_FIELD. - unsigned int i, j; - crypto_word_t t = 0, u = 0, v = 0, UV[2]; - unsigned int carry = 0; - - for (i = 0; i < NWORDS_FIELD; i++) { - for (j = 0; j <= i; j++) { - MUL(a[j], b[i-j], UV+1, UV[0]); - ADDC(0, UV[0], v, carry, v); - ADDC(carry, UV[1], u, carry, u); - t += carry; - } - c[i] = v; - v = u; - u = t; - t = 0; - } - - for (i = NWORDS_FIELD; i < 2*NWORDS_FIELD-1; i++) { - for (j = i-NWORDS_FIELD+1; j < NWORDS_FIELD; j++) { - MUL(a[j], b[i-j], UV+1, UV[0]); - ADDC(0, UV[0], v, carry, v); - ADDC(carry, UV[1], u, carry, u); - t += carry; - } - c[i] = v; - v = u; - u = t; - t = 0; - } - c[2*NWORDS_FIELD-1] = v; -} - -void sike_fprdc(felm_t ma, felm_t mc) -{ // Efficient Montgomery reduction using comba and exploiting the special form of the prime p434. - // mc = ma*R^-1 mod p434x2, where R = 2^448. - // If ma < 2^448*p434, the output mc is in the range [0, 2*p434-1]. - // ma is assumed to be in Montgomery representation. - unsigned int i, j, carry, count = ZERO_WORDS; - crypto_word_t UV[2], t = 0, u = 0, v = 0; - - for (i = 0; i < NWORDS_FIELD; i++) { - mc[i] = 0; - } - - for (i = 0; i < NWORDS_FIELD; i++) { - for (j = 0; j < i; j++) { - if (j < (i-ZERO_WORDS+1)) { - MUL(mc[j], sike_params.prime_p1[i-j], UV+1, UV[0]); - ADDC(0, UV[0], v, carry, v); - ADDC(carry, UV[1], u, carry, u); - t += carry; - } - } - ADDC(0, v, ma[i], carry, v); - ADDC(carry, u, 0, carry, u); - t += carry; - mc[i] = v; - v = u; - u = t; - t = 0; - } - - for (i = NWORDS_FIELD; i < 2*NWORDS_FIELD-1; i++) { - if (count > 0) { - count -= 1; - } - for (j = i-NWORDS_FIELD+1; j < NWORDS_FIELD; j++) { - if (j < (NWORDS_FIELD-count)) { - MUL(mc[j], sike_params.prime_p1[i-j], UV+1, UV[0]); - ADDC(0, UV[0], v, carry, v); - ADDC(carry, UV[1], u, carry, u); - t += carry; - } - } - ADDC(0, v, ma[i], carry, v); - ADDC(carry, u, 0, carry, u); - t += carry; - mc[i-NWORDS_FIELD] = v; - v = u; - u = t; - t = 0; - } - ADDC(0, v, ma[2*NWORDS_FIELD-1], carry, v); - mc[NWORDS_FIELD-1] = v; -} - -#endif // NO_ASM || (!X86_64 && !AARCH64) diff --git a/third_party/sike/curve_params.c b/third_party/sike/curve_params.c deleted file mode 100644 index a1fbb3f176..0000000000 --- a/third_party/sike/curve_params.c +++ /dev/null @@ -1,128 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: supersingular isogeny parameters and generation of functions for P434 -*********************************************************************************************/ - -#include "utils.h" - -// Parameters for isogeny system "SIKE" -const struct params_t sike_params = { - .prime = { - U64_TO_WORDS(0xFFFFFFFFFFFFFFFF), U64_TO_WORDS(0xFFFFFFFFFFFFFFFF), - U64_TO_WORDS(0xFFFFFFFFFFFFFFFF), U64_TO_WORDS(0xFDC1767AE2FFFFFF), - U64_TO_WORDS(0x7BC65C783158AEA3), U64_TO_WORDS(0x6CFC5FD681C52056), - U64_TO_WORDS(0x0002341F27177344) - }, - .prime_p1 = { - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0xFDC1767AE3000000), - U64_TO_WORDS(0x7BC65C783158AEA3), U64_TO_WORDS(0x6CFC5FD681C52056), - U64_TO_WORDS(0x0002341F27177344) - }, - .prime_x2 = { - U64_TO_WORDS(0xFFFFFFFFFFFFFFFE), U64_TO_WORDS(0xFFFFFFFFFFFFFFFF), - U64_TO_WORDS(0xFFFFFFFFFFFFFFFF), U64_TO_WORDS(0xFB82ECF5C5FFFFFF), - U64_TO_WORDS(0xF78CB8F062B15D47), U64_TO_WORDS(0xD9F8BFAD038A40AC), - U64_TO_WORDS(0x0004683E4E2EE688) - }, - .A_gen = { - U64_TO_WORDS(0x05ADF455C5C345BF), U64_TO_WORDS(0x91935C5CC767AC2B), - U64_TO_WORDS(0xAFE4E879951F0257), U64_TO_WORDS(0x70E792DC89FA27B1), - U64_TO_WORDS(0xF797F526BB48C8CD), U64_TO_WORDS(0x2181DB6131AF621F), - U64_TO_WORDS(0x00000A1C08B1ECC4), // XPA0 - U64_TO_WORDS(0x74840EB87CDA7788), U64_TO_WORDS(0x2971AA0ECF9F9D0B), - U64_TO_WORDS(0xCB5732BDF41715D5), U64_TO_WORDS(0x8CD8E51F7AACFFAA), - U64_TO_WORDS(0xA7F424730D7E419F), U64_TO_WORDS(0xD671EB919A179E8C), - U64_TO_WORDS(0x0000FFA26C5A924A), // XPA1 - U64_TO_WORDS(0xFEC6E64588B7273B), U64_TO_WORDS(0xD2A626D74CBBF1C6), - U64_TO_WORDS(0xF8F58F07A78098C7), U64_TO_WORDS(0xE23941F470841B03), - U64_TO_WORDS(0x1B63EDA2045538DD), U64_TO_WORDS(0x735CFEB0FFD49215), - U64_TO_WORDS(0x0001C4CB77542876), // XQA0 - U64_TO_WORDS(0xADB0F733C17FFDD6), U64_TO_WORDS(0x6AFFBD037DA0A050), - U64_TO_WORDS(0x680EC43DB144E02F), U64_TO_WORDS(0x1E2E5D5FF524E374), - U64_TO_WORDS(0xE2DDA115260E2995), U64_TO_WORDS(0xA6E4B552E2EDE508), - U64_TO_WORDS(0x00018ECCDDF4B53E), // XQA1 - U64_TO_WORDS(0x01BA4DB518CD6C7D), U64_TO_WORDS(0x2CB0251FE3CC0611), - U64_TO_WORDS(0x259B0C6949A9121B), U64_TO_WORDS(0x60E17AC16D2F82AD), - U64_TO_WORDS(0x3AA41F1CE175D92D), U64_TO_WORDS(0x413FBE6A9B9BC4F3), - U64_TO_WORDS(0x00022A81D8D55643), // XRA0 - U64_TO_WORDS(0xB8ADBC70FC82E54A), U64_TO_WORDS(0xEF9CDDB0D5FADDED), - U64_TO_WORDS(0x5820C734C80096A0), U64_TO_WORDS(0x7799994BAA96E0E4), - U64_TO_WORDS(0x044961599E379AF8), U64_TO_WORDS(0xDB2B94FBF09F27E2), - U64_TO_WORDS(0x0000B87FC716C0C6) // XRA1 - }, - .B_gen = { - U64_TO_WORDS(0x6E5497556EDD48A3), U64_TO_WORDS(0x2A61B501546F1C05), - U64_TO_WORDS(0xEB919446D049887D), U64_TO_WORDS(0x5864A4A69D450C4F), - U64_TO_WORDS(0xB883F276A6490D2B), U64_TO_WORDS(0x22CC287022D5F5B9), - U64_TO_WORDS(0x0001BED4772E551F), // XPB0 - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), // XPB1 - U64_TO_WORDS(0xFAE2A3F93D8B6B8E), U64_TO_WORDS(0x494871F51700FE1C), - U64_TO_WORDS(0xEF1A94228413C27C), U64_TO_WORDS(0x498FF4A4AF60BD62), - U64_TO_WORDS(0xB00AD2A708267E8A), U64_TO_WORDS(0xF4328294E017837F), - U64_TO_WORDS(0x000034080181D8AE), // XQB0 - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), // XQB1 - U64_TO_WORDS(0x283B34FAFEFDC8E4), U64_TO_WORDS(0x9208F44977C3E647), - U64_TO_WORDS(0x7DEAE962816F4E9A), U64_TO_WORDS(0x68A2BA8AA262EC9D), - U64_TO_WORDS(0x8176F112EA43F45B), U64_TO_WORDS(0x02106D022634F504), - U64_TO_WORDS(0x00007E8A50F02E37), // XRB0 - U64_TO_WORDS(0xB378B7C1DA22CCB1), U64_TO_WORDS(0x6D089C99AD1D9230), - U64_TO_WORDS(0xEBE15711813E2369), U64_TO_WORDS(0x2B35A68239D48A53), - U64_TO_WORDS(0x445F6FD138407C93), U64_TO_WORDS(0xBEF93B29A3F6B54B), - U64_TO_WORDS(0x000173FA910377D3) // XRB1 - }, - .mont_R2 = { - U64_TO_WORDS(0x28E55B65DCD69B30), U64_TO_WORDS(0xACEC7367768798C2), - U64_TO_WORDS(0xAB27973F8311688D), U64_TO_WORDS(0x175CC6AF8D6C7C0B), - U64_TO_WORDS(0xABCD92BF2DDE347E), U64_TO_WORDS(0x69E16A61C7686D9A), - U64_TO_WORDS(0x000025A89BCDD12A) - }, - .mont_one = { - U64_TO_WORDS(0x000000000000742C), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0xB90FF404FC000000), - U64_TO_WORDS(0xD801A4FB559FACD4), U64_TO_WORDS(0xE93254545F77410C), - U64_TO_WORDS(0x0000ECEEA7BD2EDA) - }, - .mont_six = { - U64_TO_WORDS(0x000000000002B90A), U64_TO_WORDS(0x0000000000000000), - U64_TO_WORDS(0x0000000000000000), U64_TO_WORDS(0x5ADCCB2822000000), - U64_TO_WORDS(0x187D24F39F0CAFB4), U64_TO_WORDS(0x9D353A4D394145A0), - U64_TO_WORDS(0x00012559A0403298) - }, - .A_strat = { - 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_strat = { - 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 - } -}; diff --git a/third_party/sike/fpx.c b/third_party/sike/fpx.c deleted file mode 100644 index 9917116c32..0000000000 --- a/third_party/sike/fpx.c +++ /dev/null @@ -1,283 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: core functions over GF(p) and GF(p^2) -*********************************************************************************************/ -#include - -#include "utils.h" -#include "fpx.h" - -extern const struct params_t sike_params; - -// Multiprecision squaring, c = a^2 mod p. -static void fpsqr_mont(const felm_t ma, felm_t mc) -{ - dfelm_t temp = {0}; - sike_mpmul(ma, ma, temp); - sike_fprdc(temp, mc); -} - -// Chain to compute a^(p-3)/4 using Montgomery arithmetic. -static void fpinv_chain_mont(felm_t a) -{ - unsigned int i, j; - felm_t t[31], tt; - - // Precomputed table - fpsqr_mont(a, tt); - sike_fpmul_mont(a, tt, t[0]); - for (i = 0; i <= 29; i++) sike_fpmul_mont(t[i], tt, t[i+1]); - - sike_fpcopy(a, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[5], tt, tt); - for (i = 0; i < 10; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[14], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[3], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[23], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[13], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[24], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[7], tt, tt); - for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[12], tt, tt); - for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[30], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[1], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[30], tt, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[21], tt, tt); - for (i = 0; i < 9; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[2], tt, tt); - for (i = 0; i < 9; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[19], tt, tt); - for (i = 0; i < 9; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[1], tt, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[24], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[26], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[16], tt, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[10], tt, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[6], tt, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[0], tt, tt); - for (i = 0; i < 9; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[20], tt, tt); - for (i = 0; i < 8; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[9], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[25], tt, tt); - for (i = 0; i < 9; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[30], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[26], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(a, tt, tt); - for (i = 0; i < 7; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[28], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[6], tt, tt); - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[10], tt, tt); - for (i = 0; i < 9; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[22], tt, tt); - for (j = 0; j < 35; j++) { - for (i = 0; i < 6; i++) fpsqr_mont(tt, tt); - sike_fpmul_mont(t[30], tt, tt); - } - sike_fpcopy(tt, a); -} - -// Field inversion using Montgomery arithmetic, a = a^(-1)*R mod p. -static void fpinv_mont(felm_t a) -{ - felm_t tt = {0}; - sike_fpcopy(a, tt); - fpinv_chain_mont(tt); - fpsqr_mont(tt, tt); - fpsqr_mont(tt, tt); - sike_fpmul_mont(a, tt, a); -} - -// Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit. -#if defined(OPENSSL_NO_ASM) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_AARCH64)) -inline static unsigned int mp_add(const felm_t a, const felm_t b, felm_t c, const unsigned int nwords) { - uint8_t carry = 0; - for (size_t i = 0; i < nwords; i++) { - ADDC(carry, a[i], b[i], carry, c[i]); - } - return carry; -} - -// Multiprecision subtraction, c = a-b, where lng(a) = lng(b) = nwords. Returns the borrow bit. -inline static unsigned int mp_sub(const felm_t a, const felm_t b, felm_t c, const unsigned int nwords) { - uint32_t borrow = 0; - for (size_t i = 0; i < nwords; i++) { - SUBC(borrow, a[i], b[i], borrow, c[i]); - } - return borrow; -} -#endif - -// Multiprecision addition, c = a+b. -inline static void mp_addfast(const felm_t a, const felm_t b, felm_t c) -{ -#if defined(OPENSSL_NO_ASM) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_AARCH64)) - mp_add(a, b, c, NWORDS_FIELD); -#else - sike_mpadd_asm(a, b, c); -#endif -} - -// Multiprecision subtraction, c = a-b, where lng(a) = lng(b) = 2*NWORDS_FIELD. -// If c < 0 then returns mask = 0xFF..F, else mask = 0x00..0 -inline static crypto_word_t mp_subfast(const dfelm_t a, const dfelm_t b, dfelm_t c) { -#if defined(OPENSSL_NO_ASM) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_AARCH64)) - return (0 - (crypto_word_t)mp_sub(a, b, c, 2*NWORDS_FIELD)); -#else - return sike_mpsubx2_asm(a, b, c); -#endif -} - -// Multiprecision subtraction, c = c-a-b, where lng(a) = lng(b) = 2*NWORDS_FIELD. -// Inputs should be s.t. c > a and c > b -inline static void mp_dblsubfast(const dfelm_t a, const dfelm_t b, dfelm_t c) { -#if defined(OPENSSL_NO_ASM) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_AARCH64)) - mp_sub(c, a, c, 2*NWORDS_FIELD); - mp_sub(c, b, c, 2*NWORDS_FIELD); -#else - sike_mpdblsubx2_asm(a, b, c); -#endif -} - -// Copy a field element, c = a. -void sike_fpcopy(const felm_t a, felm_t c) { - for (size_t i = 0; i < NWORDS_FIELD; i++) { - c[i] = a[i]; - } -} - -// Field multiplication using Montgomery arithmetic, c = a*b*R^-1 mod prime, where R=2^768 -void sike_fpmul_mont(const felm_t ma, const felm_t mb, felm_t mc) -{ - dfelm_t temp = {0}; - sike_mpmul(ma, mb, temp); - sike_fprdc(temp, mc); -} - -// Conversion from Montgomery representation to standard representation, -// c = ma*R^(-1) mod p = a mod p, where ma in [0, p-1]. -void sike_from_mont(const felm_t ma, felm_t c) -{ - felm_t one = {0}; - one[0] = 1; - - sike_fpmul_mont(ma, one, c); - sike_fpcorrection(c); -} - -// GF(p^2) squaring using Montgomery arithmetic, c = a^2 in GF(p^2). -// Inputs: a = a0+a1*i, where a0, a1 are in [0, 2*p-1] -// Output: c = c0+c1*i, where c0, c1 are in [0, 2*p-1] -void sike_fp2sqr_mont(const f2elm_t a, f2elm_t c) { - felm_t t1, t2, t3; - - mp_addfast(a->c0, a->c1, t1); // t1 = a0+a1 - sike_fpsub(a->c0, a->c1, t2); // t2 = a0-a1 - mp_addfast(a->c0, a->c0, t3); // t3 = 2a0 - sike_fpmul_mont(t1, t2, c->c0); // c0 = (a0+a1)(a0-a1) - sike_fpmul_mont(t3, a->c1, c->c1); // c1 = 2a0*a1 -} - -// Modular negation, a = -a mod p503. -// Input/output: a in [0, 2*p503-1] -void sike_fpneg(felm_t a) { - uint32_t borrow = 0; - for (size_t i = 0; i < NWORDS_FIELD; i++) { - SUBC(borrow, sike_params.prime_x2[i], a[i], borrow, a[i]); - } -} - -// Modular division by two, c = a/2 mod p503. -// Input : a in [0, 2*p503-1] -// Output: c in [0, 2*p503-1] -void sike_fpdiv2(const felm_t a, felm_t c) { - uint32_t carry = 0; - crypto_word_t mask; - - mask = 0 - (crypto_word_t)(a[0] & 1); // If a is odd compute a+p503 - for (size_t i = 0; i < NWORDS_FIELD; i++) { - ADDC(carry, a[i], sike_params.prime[i] & mask, carry, c[i]); - } - - // Multiprecision right shift by one. - for (size_t i = 0; i < NWORDS_FIELD-1; i++) { - c[i] = (c[i] >> 1) ^ (c[i+1] << (RADIX - 1)); - } - c[NWORDS_FIELD-1] >>= 1; -} - -// Modular correction to reduce field element a in [0, 2*p503-1] to [0, p503-1]. -void sike_fpcorrection(felm_t a) { - uint32_t borrow = 0; - crypto_word_t mask; - - for (size_t i = 0; i < NWORDS_FIELD; i++) { - SUBC(borrow, a[i], sike_params.prime[i], borrow, a[i]); - } - mask = 0 - (crypto_word_t)borrow; - - borrow = 0; - for (size_t i = 0; i < NWORDS_FIELD; i++) { - ADDC(borrow, a[i], sike_params.prime[i] & mask, borrow, a[i]); - } -} - -// GF(p^2) multiplication using Montgomery arithmetic, c = a*b in GF(p^2). -// Inputs: a = a0+a1*i and b = b0+b1*i, where a0, a1, b0, b1 are in [0, 2*p-1] -// Output: c = c0+c1*i, where c0, c1 are in [0, 2*p-1] -void sike_fp2mul_mont(const f2elm_t a, const f2elm_t b, f2elm_t c) { - felm_t t1, t2; - dfelm_t tt1, tt2, tt3; - crypto_word_t mask; - - mp_addfast(a->c0, a->c1, t1); // t1 = a0+a1 - mp_addfast(b->c0, b->c1, t2); // t2 = b0+b1 - sike_mpmul(a->c0, b->c0, tt1); // tt1 = a0*b0 - sike_mpmul(a->c1, b->c1, tt2); // tt2 = a1*b1 - sike_mpmul(t1, t2, tt3); // tt3 = (a0+a1)*(b0+b1) - mp_dblsubfast(tt1, tt2, tt3); // tt3 = (a0+a1)*(b0+b1) - a0*b0 - a1*b1 - mask = mp_subfast(tt1, tt2, tt1); // tt1 = a0*b0 - a1*b1. If tt1 < 0 then mask = 0xFF..F, else if tt1 >= 0 then mask = 0x00..0 - - for (size_t i = 0; i < NWORDS_FIELD; i++) { - t1[i] = sike_params.prime[i] & mask; - } - - sike_fprdc(tt3, c->c1); // c[1] = (a0+a1)*(b0+b1) - a0*b0 - a1*b1 - mp_addfast(&tt1[NWORDS_FIELD], t1, &tt1[NWORDS_FIELD]); - sike_fprdc(tt1, c->c0); // c[0] = a0*b0 - a1*b1 -} - -// GF(p^2) inversion using Montgomery arithmetic, a = (a0-i*a1)/(a0^2+a1^2). -void sike_fp2inv_mont(f2elm_t a) { - f2elm_t t1; - - fpsqr_mont(a->c0, t1->c0); // t10 = a0^2 - fpsqr_mont(a->c1, t1->c1); // t11 = a1^2 - sike_fpadd(t1->c0, t1->c1, t1->c0); // t10 = a0^2+a1^2 - fpinv_mont(t1->c0); // t10 = (a0^2+a1^2)^-1 - sike_fpneg(a->c1); // a = a0-i*a1 - sike_fpmul_mont(a->c0, t1->c0, a->c0); - sike_fpmul_mont(a->c1, t1->c0, a->c1); // a = (a0-i*a1)*(a0^2+a1^2)^-1 -} diff --git a/third_party/sike/fpx.h b/third_party/sike/fpx.h deleted file mode 100644 index e69768857c..0000000000 --- a/third_party/sike/fpx.h +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef FPX_H_ -#define FPX_H_ - -#include "utils.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -// Modular addition, c = a+b mod p. -void sike_fpadd(const felm_t a, const felm_t b, felm_t c); -// Modular subtraction, c = a-b mod p. -void sike_fpsub(const felm_t a, const felm_t b, felm_t c); -// Modular division by two, c = a/2 mod p. -void sike_fpdiv2(const felm_t a, felm_t c); -// Modular correction to reduce field element a in [0, 2*p-1] to [0, p-1]. -void sike_fpcorrection(felm_t a); -// Multiprecision multiply, c = a*b, where lng(a) = lng(b) = nwords. -void sike_mpmul(const felm_t a, const felm_t b, dfelm_t c); -// 443-bit Montgomery reduction, c = a mod p. Buffer 'a' is modified after -// call returns. -void sike_fprdc(dfelm_t a, felm_t c); -// Double 2x443-bit multiprecision subtraction, c = c-a-b -void sike_mpdblsubx2_asm(const felm_t a, const felm_t b, felm_t c); -// Multiprecision subtraction, c = a-b -crypto_word_t sike_mpsubx2_asm(const dfelm_t a, const dfelm_t b, dfelm_t c); -// 443-bit multiprecision addition, c = a+b -void sike_mpadd_asm(const felm_t a, const felm_t b, felm_t c); -// Modular negation, a = -a mod p. -void sike_fpneg(felm_t a); -// Copy of a field element, c = a -void sike_fpcopy(const felm_t a, felm_t c); -// Copy a field element, c = a. -void sike_fpzero(felm_t a); -// If option = 0xFF...FF x=y; y=x, otherwise swap doesn't happen. Constant time. -void sike_cswap_asm(point_proj_t x, point_proj_t y, const crypto_word_t option); -// Conversion from Montgomery representation to standard representation, -// c = ma*R^(-1) mod p = a mod p, where ma in [0, p-1]. -void sike_from_mont(const felm_t ma, felm_t c); -// Field multiplication using Montgomery arithmetic, c = a*b*R^-1 mod p443, where R=2^768 -void sike_fpmul_mont(const felm_t ma, const felm_t mb, felm_t mc); -// GF(p443^2) multiplication using Montgomery arithmetic, c = a*b in GF(p443^2) -void sike_fp2mul_mont(const f2elm_t a, const f2elm_t b, f2elm_t c); -// GF(p443^2) inversion using Montgomery arithmetic, a = (a0-i*a1)/(a0^2+a1^2) -void sike_fp2inv_mont(f2elm_t a); -// GF(p^2) squaring using Montgomery arithmetic, c = a^2 in GF(p^2). -void sike_fp2sqr_mont(const f2elm_t a, f2elm_t c); -// Modular correction, a = a in GF(p^2). -void sike_fp2correction(f2elm_t a); - -#if defined(__cplusplus) -} // extern C -#endif - -// GF(p^2) addition, c = a+b in GF(p^2). -#define sike_fp2add(a, b, c) \ -do { \ - sike_fpadd(a->c0, b->c0, c->c0); \ - sike_fpadd(a->c1, b->c1, c->c1); \ -} while(0) - -// GF(p^2) subtraction, c = a-b in GF(p^2). -#define sike_fp2sub(a,b,c) \ -do { \ - sike_fpsub(a->c0, b->c0, c->c0); \ - sike_fpsub(a->c1, b->c1, c->c1); \ -} while(0) - -// Copy a GF(p^2) element, c = a. -#define sike_fp2copy(a, c) \ -do { \ - sike_fpcopy(a->c0, c->c0); \ - sike_fpcopy(a->c1, c->c1); \ -} while(0) - -// GF(p^2) negation, a = -a in GF(p^2). -#define sike_fp2neg(a) \ -do { \ - sike_fpneg(a->c0); \ - sike_fpneg(a->c1); \ -} while(0) - -// GF(p^2) division by two, c = a/2 in GF(p^2). -#define sike_fp2div2(a, c) \ -do { \ - sike_fpdiv2(a->c0, c->c0); \ - sike_fpdiv2(a->c1, c->c1); \ -} while(0) - -// Modular correction, a = a in GF(p^2). -#define sike_fp2correction(a) \ -do { \ - sike_fpcorrection(a->c0); \ - sike_fpcorrection(a->c1); \ -} while(0) - -// Conversion of a GF(p^2) element to Montgomery representation, -// mc_i = a_i*R^2*R^(-1) = a_i*R in GF(p^2). -#define sike_to_fp2mont(a, mc) \ - do { \ - sike_fpmul_mont(a->c0, sike_params.mont_R2, mc->c0); \ - sike_fpmul_mont(a->c1, sike_params.mont_R2, mc->c1); \ - } while (0) - -// Conversion of a GF(p^2) element from Montgomery representation to standard representation, -// c_i = ma_i*R^(-1) = a_i in GF(p^2). -#define sike_from_fp2mont(ma, c) \ -do { \ - sike_from_mont(ma->c0, c->c0); \ - sike_from_mont(ma->c1, c->c1); \ -} while(0) - -#endif // FPX_H_ diff --git a/third_party/sike/isogeny.c b/third_party/sike/isogeny.c deleted file mode 100644 index 6b910e02b4..0000000000 --- a/third_party/sike/isogeny.c +++ /dev/null @@ -1,260 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: elliptic curve and isogeny functions -*********************************************************************************************/ -#include "utils.h" -#include "isogeny.h" -#include "fpx.h" - -static void xDBL(const point_proj_t P, point_proj_t Q, const f2elm_t A24plus, const f2elm_t C24) -{ // Doubling of a Montgomery point in projective coordinates (X:Z). - // Input: projective Montgomery x-coordinates P = (X1:Z1), where x1=X1/Z1 and Montgomery curve constants A+2C and 4C. - // Output: projective Montgomery x-coordinates Q = 2*P = (X2:Z2). - f2elm_t t0, t1; - - sike_fp2sub(P->X, P->Z, t0); // t0 = X1-Z1 - sike_fp2add(P->X, P->Z, t1); // t1 = X1+Z1 - sike_fp2sqr_mont(t0, t0); // t0 = (X1-Z1)^2 - sike_fp2sqr_mont(t1, t1); // t1 = (X1+Z1)^2 - sike_fp2mul_mont(C24, t0, Q->Z); // Z2 = C24*(X1-Z1)^2 - sike_fp2mul_mont(t1, Q->Z, Q->X); // X2 = C24*(X1-Z1)^2*(X1+Z1)^2 - sike_fp2sub(t1, t0, t1); // t1 = (X1+Z1)^2-(X1-Z1)^2 - sike_fp2mul_mont(A24plus, t1, t0); // t0 = A24plus*[(X1+Z1)^2-(X1-Z1)^2] - sike_fp2add(Q->Z, t0, Q->Z); // Z2 = A24plus*[(X1+Z1)^2-(X1-Z1)^2] + C24*(X1-Z1)^2 - sike_fp2mul_mont(Q->Z, t1, Q->Z); // Z2 = [A24plus*[(X1+Z1)^2-(X1-Z1)^2] + C24*(X1-Z1)^2]*[(X1+Z1)^2-(X1-Z1)^2] -} - -void sike_xDBLe(const point_proj_t P, point_proj_t Q, const f2elm_t A24plus, const f2elm_t C24, size_t e) -{ // Computes [2^e](X:Z) on Montgomery curve with projective constant via e repeated doublings. - // Input: projective Montgomery x-coordinates P = (XP:ZP), such that xP=XP/ZP and Montgomery curve constants A+2C and 4C. - // Output: projective Montgomery x-coordinates Q <- (2^e)*P. - - memmove(Q, P, sizeof(*P)); - for (size_t i = 0; i < e; i++) { - xDBL(Q, Q, A24plus, C24); - } -} - -void sike_get_4_isog(const point_proj_t P, f2elm_t A24plus, f2elm_t C24, f2elm_t* coeff) -{ // Computes the corresponding 4-isogeny of a projective Montgomery point (X4:Z4) of order 4. - // Input: projective point of order four P = (X4:Z4). - // Output: the 4-isogenous Montgomery curve with projective coefficients A+2C/4C and the 3 coefficients - // that are used to evaluate the isogeny at a point in eval_4_isog(). - - sike_fp2sub(P->X, P->Z, coeff[1]); // coeff[1] = X4-Z4 - sike_fp2add(P->X, P->Z, coeff[2]); // coeff[2] = X4+Z4 - sike_fp2sqr_mont(P->Z, coeff[0]); // coeff[0] = Z4^2 - sike_fp2add(coeff[0], coeff[0], coeff[0]); // coeff[0] = 2*Z4^2 - sike_fp2sqr_mont(coeff[0], C24); // C24 = 4*Z4^4 - sike_fp2add(coeff[0], coeff[0], coeff[0]); // coeff[0] = 4*Z4^2 - sike_fp2sqr_mont(P->X, A24plus); // A24plus = X4^2 - sike_fp2add(A24plus, A24plus, A24plus); // A24plus = 2*X4^2 - sike_fp2sqr_mont(A24plus, A24plus); // A24plus = 4*X4^4 -} - -void sike_eval_4_isog(point_proj_t P, f2elm_t* coeff) -{ // Evaluates the isogeny at the point (X:Z) in the domain of the isogeny, given a 4-isogeny phi defined - // by the 3 coefficients in coeff (computed in the function get_4_isog()). - // Inputs: the coefficients defining the isogeny, and the projective point P = (X:Z). - // Output: the projective point P = phi(P) = (X:Z) in the codomain. - f2elm_t t0, t1; - - sike_fp2add(P->X, P->Z, t0); // t0 = X+Z - sike_fp2sub(P->X, P->Z, t1); // t1 = X-Z - sike_fp2mul_mont(t0, coeff[1], P->X); // X = (X+Z)*coeff[1] - sike_fp2mul_mont(t1, coeff[2], P->Z); // Z = (X-Z)*coeff[2] - sike_fp2mul_mont(t0, t1, t0); // t0 = (X+Z)*(X-Z) - sike_fp2mul_mont(t0, coeff[0], t0); // t0 = coeff[0]*(X+Z)*(X-Z) - sike_fp2add(P->X, P->Z, t1); // t1 = (X-Z)*coeff[2] + (X+Z)*coeff[1] - sike_fp2sub(P->X, P->Z, P->Z); // Z = (X-Z)*coeff[2] - (X+Z)*coeff[1] - sike_fp2sqr_mont(t1, t1); // t1 = [(X-Z)*coeff[2] + (X+Z)*coeff[1]]^2 - sike_fp2sqr_mont(P->Z, P->Z); // Z = [(X-Z)*coeff[2] - (X+Z)*coeff[1]]^2 - sike_fp2add(t1, t0, P->X); // X = coeff[0]*(X+Z)*(X-Z) + [(X-Z)*coeff[2] + (X+Z)*coeff[1]]^2 - sike_fp2sub(P->Z, t0, t0); // t0 = [(X-Z)*coeff[2] - (X+Z)*coeff[1]]^2 - coeff[0]*(X+Z)*(X-Z) - sike_fp2mul_mont(P->X, t1, P->X); // Xfinal - sike_fp2mul_mont(P->Z, t0, P->Z); // Zfinal -} - - -void sike_xTPL(const point_proj_t P, point_proj_t Q, const f2elm_t A24minus, const f2elm_t A24plus) -{ // Tripling of a Montgomery point in projective coordinates (X:Z). - // Input: projective Montgomery x-coordinates P = (X:Z), where x=X/Z and Montgomery curve constants A24plus = A+2C and A24minus = A-2C. - // Output: projective Montgomery x-coordinates Q = 3*P = (X3:Z3). - f2elm_t t0, t1, t2, t3, t4, t5, t6; - - sike_fp2sub(P->X, P->Z, t0); // t0 = X-Z - sike_fp2sqr_mont(t0, t2); // t2 = (X-Z)^2 - sike_fp2add(P->X, P->Z, t1); // t1 = X+Z - sike_fp2sqr_mont(t1, t3); // t3 = (X+Z)^2 - sike_fp2add(t0, t1, t4); // t4 = 2*X - sike_fp2sub(t1, t0, t0); // t0 = 2*Z - sike_fp2sqr_mont(t4, t1); // t1 = 4*X^2 - sike_fp2sub(t1, t3, t1); // t1 = 4*X^2 - (X+Z)^2 - sike_fp2sub(t1, t2, t1); // t1 = 4*X^2 - (X+Z)^2 - (X-Z)^2 - sike_fp2mul_mont(t3, A24plus, t5); // t5 = A24plus*(X+Z)^2 - sike_fp2mul_mont(t3, t5, t3); // t3 = A24plus*(X+Z)^3 - sike_fp2mul_mont(A24minus, t2, t6); // t6 = A24minus*(X-Z)^2 - sike_fp2mul_mont(t2, t6, t2); // t2 = A24minus*(X-Z)^3 - sike_fp2sub(t2, t3, t3); // t3 = A24minus*(X-Z)^3 - coeff*(X+Z)^3 - sike_fp2sub(t5, t6, t2); // t2 = A24plus*(X+Z)^2 - A24minus*(X-Z)^2 - sike_fp2mul_mont(t1, t2, t1); // t1 = [4*X^2 - (X+Z)^2 - (X-Z)^2]*[A24plus*(X+Z)^2 - A24minus*(X-Z)^2] - sike_fp2add(t3, t1, t2); // t2 = [4*X^2 - (X+Z)^2 - (X-Z)^2]*[A24plus*(X+Z)^2 - A24minus*(X-Z)^2] + A24minus*(X-Z)^3 - coeff*(X+Z)^3 - sike_fp2sqr_mont(t2, t2); // t2 = t2^2 - sike_fp2mul_mont(t4, t2, Q->X); // X3 = 2*X*t2 - sike_fp2sub(t3, t1, t1); // t1 = A24minus*(X-Z)^3 - A24plus*(X+Z)^3 - [4*X^2 - (X+Z)^2 - (X-Z)^2]*[A24plus*(X+Z)^2 - A24minus*(X-Z)^2] - sike_fp2sqr_mont(t1, t1); // t1 = t1^2 - sike_fp2mul_mont(t0, t1, Q->Z); // Z3 = 2*Z*t1 -} - -void sike_xTPLe(const point_proj_t P, point_proj_t Q, const f2elm_t A24minus, const f2elm_t A24plus, size_t e) -{ // Computes [3^e](X:Z) on Montgomery curve with projective constant via e repeated triplings. - // Input: projective Montgomery x-coordinates P = (XP:ZP), such that xP=XP/ZP and Montgomery curve constants A24plus = A+2C and A24minus = A-2C. - // Output: projective Montgomery x-coordinates Q <- (3^e)*P. - memmove(Q, P, sizeof(*P)); - for (size_t i = 0; i < e; i++) { - sike_xTPL(Q, Q, A24minus, A24plus); - } -} - -void sike_get_3_isog(const point_proj_t P, f2elm_t A24minus, f2elm_t A24plus, f2elm_t* coeff) -{ // Computes the corresponding 3-isogeny of a projective Montgomery point (X3:Z3) of order 3. - // Input: projective point of order three P = (X3:Z3). - // Output: the 3-isogenous Montgomery curve with projective coefficient A/C. - f2elm_t t0, t1, t2, t3, t4; - - sike_fp2sub(P->X, P->Z, coeff[0]); // coeff0 = X-Z - sike_fp2sqr_mont(coeff[0], t0); // t0 = (X-Z)^2 - sike_fp2add(P->X, P->Z, coeff[1]); // coeff1 = X+Z - sike_fp2sqr_mont(coeff[1], t1); // t1 = (X+Z)^2 - sike_fp2add(t0, t1, t2); // t2 = (X+Z)^2 + (X-Z)^2 - sike_fp2add(coeff[0], coeff[1], t3); // t3 = 2*X - sike_fp2sqr_mont(t3, t3); // t3 = 4*X^2 - sike_fp2sub(t3, t2, t3); // t3 = 4*X^2 - (X+Z)^2 - (X-Z)^2 - sike_fp2add(t1, t3, t2); // t2 = 4*X^2 - (X-Z)^2 - sike_fp2add(t3, t0, t3); // t3 = 4*X^2 - (X+Z)^2 - sike_fp2add(t0, t3, t4); // t4 = 4*X^2 - (X+Z)^2 + (X-Z)^2 - sike_fp2add(t4, t4, t4); // t4 = 2(4*X^2 - (X+Z)^2 + (X-Z)^2) - sike_fp2add(t1, t4, t4); // t4 = 8*X^2 - (X+Z)^2 + 2*(X-Z)^2 - sike_fp2mul_mont(t2, t4, A24minus); // A24minus = [4*X^2 - (X-Z)^2]*[8*X^2 - (X+Z)^2 + 2*(X-Z)^2] - sike_fp2add(t1, t2, t4); // t4 = 4*X^2 + (X+Z)^2 - (X-Z)^2 - sike_fp2add(t4, t4, t4); // t4 = 2(4*X^2 + (X+Z)^2 - (X-Z)^2) - sike_fp2add(t0, t4, t4); // t4 = 8*X^2 + 2*(X+Z)^2 - (X-Z)^2 - sike_fp2mul_mont(t3, t4, t4); // t4 = [4*X^2 - (X+Z)^2]*[8*X^2 + 2*(X+Z)^2 - (X-Z)^2] - sike_fp2sub(t4, A24minus, t0); // t0 = [4*X^2 - (X+Z)^2]*[8*X^2 + 2*(X+Z)^2 - (X-Z)^2] - [4*X^2 - (X-Z)^2]*[8*X^2 - (X+Z)^2 + 2*(X-Z)^2] - sike_fp2add(A24minus, t0, A24plus); // A24plus = 8*X^2 - (X+Z)^2 + 2*(X-Z)^2 -} - - -void sike_eval_3_isog(point_proj_t Q, f2elm_t* coeff) -{ // Computes the 3-isogeny R=phi(X:Z), given projective point (X3:Z3) of order 3 on a Montgomery curve and - // a point P with 2 coefficients in coeff (computed in the function get_3_isog()). - // Inputs: projective points P = (X3:Z3) and Q = (X:Z). - // Output: the projective point Q <- phi(Q) = (X3:Z3). - f2elm_t t0, t1, t2; - - sike_fp2add(Q->X, Q->Z, t0); // t0 = X+Z - sike_fp2sub(Q->X, Q->Z, t1); // t1 = X-Z - sike_fp2mul_mont(t0, coeff[0], t0); // t0 = coeff0*(X+Z) - sike_fp2mul_mont(t1, coeff[1], t1); // t1 = coeff1*(X-Z) - sike_fp2add(t0, t1, t2); // t2 = coeff0*(X+Z) + coeff1*(X-Z) - sike_fp2sub(t1, t0, t0); // t0 = coeff1*(X-Z) - coeff0*(X+Z) - sike_fp2sqr_mont(t2, t2); // t2 = [coeff0*(X+Z) + coeff1*(X-Z)]^2 - sike_fp2sqr_mont(t0, t0); // t0 = [coeff1*(X-Z) - coeff0*(X+Z)]^2 - sike_fp2mul_mont(Q->X, t2, Q->X); // X3final = X*[coeff0*(X+Z) + coeff1*(X-Z)]^2 - sike_fp2mul_mont(Q->Z, t0, Q->Z); // Z3final = Z*[coeff1*(X-Z) - coeff0*(X+Z)]^2 -} - - -void sike_inv_3_way(f2elm_t z1, f2elm_t z2, f2elm_t z3) -{ // 3-way simultaneous inversion - // Input: z1,z2,z3 - // Output: 1/z1,1/z2,1/z3 (override inputs). - f2elm_t t0, t1, t2, t3; - - sike_fp2mul_mont(z1, z2, t0); // t0 = z1*z2 - sike_fp2mul_mont(z3, t0, t1); // t1 = z1*z2*z3 - sike_fp2inv_mont(t1); // t1 = 1/(z1*z2*z3) - sike_fp2mul_mont(z3, t1, t2); // t2 = 1/(z1*z2) - sike_fp2mul_mont(t2, z2, t3); // t3 = 1/z1 - sike_fp2mul_mont(t2, z1, z2); // z2 = 1/z2 - sike_fp2mul_mont(t0, t1, z3); // z3 = 1/z3 - sike_fp2copy(t3, z1); // z1 = 1/z1 -} - - -void sike_get_A(const f2elm_t xP, const f2elm_t xQ, const f2elm_t xR, f2elm_t A) -{ // Given the x-coordinates of P, Q, and R, returns the value A corresponding to the Montgomery curve E_A: y^2=x^3+A*x^2+x such that R=Q-P on E_A. - // Input: the x-coordinates xP, xQ, and xR of the points P, Q and R. - // Output: the coefficient A corresponding to the curve E_A: y^2=x^3+A*x^2+x. - f2elm_t t0, t1, one = F2ELM_INIT; - - extern const struct params_t sike_params; - sike_fpcopy(sike_params.mont_one, one->c0); - sike_fp2add(xP, xQ, t1); // t1 = xP+xQ - sike_fp2mul_mont(xP, xQ, t0); // t0 = xP*xQ - sike_fp2mul_mont(xR, t1, A); // A = xR*t1 - sike_fp2add(t0, A, A); // A = A+t0 - sike_fp2mul_mont(t0, xR, t0); // t0 = t0*xR - sike_fp2sub(A, one, A); // A = A-1 - sike_fp2add(t0, t0, t0); // t0 = t0+t0 - sike_fp2add(t1, xR, t1); // t1 = t1+xR - sike_fp2add(t0, t0, t0); // t0 = t0+t0 - sike_fp2sqr_mont(A, A); // A = A^2 - sike_fp2inv_mont(t0); // t0 = 1/t0 - sike_fp2mul_mont(A, t0, A); // A = A*t0 - sike_fp2sub(A, t1, A); // Afinal = A-t1 -} - - -void sike_j_inv(const f2elm_t A, const f2elm_t C, f2elm_t jinv) -{ // Computes the j-invariant of a Montgomery curve with projective constant. - // Input: A,C in GF(p^2). - // Output: j=256*(A^2-3*C^2)^3/(C^4*(A^2-4*C^2)), which is the j-invariant of the Montgomery curve B*y^2=x^3+(A/C)*x^2+x or (equivalently) j-invariant of B'*y^2=C*x^3+A*x^2+C*x. - f2elm_t t0, t1; - - sike_fp2sqr_mont(A, jinv); // jinv = A^2 - sike_fp2sqr_mont(C, t1); // t1 = C^2 - sike_fp2add(t1, t1, t0); // t0 = t1+t1 - sike_fp2sub(jinv, t0, t0); // t0 = jinv-t0 - sike_fp2sub(t0, t1, t0); // t0 = t0-t1 - sike_fp2sub(t0, t1, jinv); // jinv = t0-t1 - sike_fp2sqr_mont(t1, t1); // t1 = t1^2 - sike_fp2mul_mont(jinv, t1, jinv); // jinv = jinv*t1 - sike_fp2add(t0, t0, t0); // t0 = t0+t0 - sike_fp2add(t0, t0, t0); // t0 = t0+t0 - sike_fp2sqr_mont(t0, t1); // t1 = t0^2 - sike_fp2mul_mont(t0, t1, t0); // t0 = t0*t1 - sike_fp2add(t0, t0, t0); // t0 = t0+t0 - sike_fp2add(t0, t0, t0); // t0 = t0+t0 - sike_fp2inv_mont(jinv); // jinv = 1/jinv - sike_fp2mul_mont(jinv, t0, jinv); // jinv = t0*jinv -} - - -void sike_xDBLADD(point_proj_t P, point_proj_t Q, const f2elm_t xPQ, const f2elm_t A24) -{ // Simultaneous doubling and differential addition. - // Input: projective Montgomery points P=(XP:ZP) and Q=(XQ:ZQ) such that xP=XP/ZP and xQ=XQ/ZQ, affine difference xPQ=x(P-Q) and Montgomery curve constant A24=(A+2)/4. - // Output: projective Montgomery points P <- 2*P = (X2P:Z2P) such that x(2P)=X2P/Z2P, and Q <- P+Q = (XQP:ZQP) such that = x(Q+P)=XQP/ZQP. - f2elm_t t0, t1, t2; - - sike_fp2add(P->X, P->Z, t0); // t0 = XP+ZP - sike_fp2sub(P->X, P->Z, t1); // t1 = XP-ZP - sike_fp2sqr_mont(t0, P->X); // XP = (XP+ZP)^2 - sike_fp2sub(Q->X, Q->Z, t2); // t2 = XQ-ZQ - sike_fp2correction(t2); - sike_fp2add(Q->X, Q->Z, Q->X); // XQ = XQ+ZQ - sike_fp2mul_mont(t0, t2, t0); // t0 = (XP+ZP)*(XQ-ZQ) - sike_fp2sqr_mont(t1, P->Z); // ZP = (XP-ZP)^2 - sike_fp2mul_mont(t1, Q->X, t1); // t1 = (XP-ZP)*(XQ+ZQ) - sike_fp2sub(P->X, P->Z, t2); // t2 = (XP+ZP)^2-(XP-ZP)^2 - sike_fp2mul_mont(P->X, P->Z, P->X); // XP = (XP+ZP)^2*(XP-ZP)^2 - sike_fp2mul_mont(t2, A24, Q->X); // XQ = A24*[(XP+ZP)^2-(XP-ZP)^2] - sike_fp2sub(t0, t1, Q->Z); // ZQ = (XP+ZP)*(XQ-ZQ)-(XP-ZP)*(XQ+ZQ) - sike_fp2add(Q->X, P->Z, P->Z); // ZP = A24*[(XP+ZP)^2-(XP-ZP)^2]+(XP-ZP)^2 - sike_fp2add(t0, t1, Q->X); // XQ = (XP+ZP)*(XQ-ZQ)+(XP-ZP)*(XQ+ZQ) - sike_fp2mul_mont(P->Z, t2, P->Z); // ZP = [A24*[(XP+ZP)^2-(XP-ZP)^2]+(XP-ZP)^2]*[(XP+ZP)^2-(XP-ZP)^2] - sike_fp2sqr_mont(Q->Z, Q->Z); // ZQ = [(XP+ZP)*(XQ-ZQ)-(XP-ZP)*(XQ+ZQ)]^2 - sike_fp2sqr_mont(Q->X, Q->X); // XQ = [(XP+ZP)*(XQ-ZQ)+(XP-ZP)*(XQ+ZQ)]^2 - sike_fp2mul_mont(Q->Z, xPQ, Q->Z); // ZQ = xPQ*[(XP+ZP)*(XQ-ZQ)-(XP-ZP)*(XQ+ZQ)]^2 -} diff --git a/third_party/sike/isogeny.h b/third_party/sike/isogeny.h deleted file mode 100644 index 18337dd262..0000000000 --- a/third_party/sike/isogeny.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef ISOGENY_H_ -#define ISOGENY_H_ - -// Computes [2^e](X:Z) on Montgomery curve with projective -// constant via e repeated doublings. -void sike_xDBLe( - const point_proj_t P, point_proj_t Q, const f2elm_t A24plus, - const f2elm_t C24, size_t e); -// Simultaneous doubling and differential addition. -void sike_xDBLADD( - point_proj_t P, point_proj_t Q, const f2elm_t xPQ, - const f2elm_t A24); -// Tripling of a Montgomery point in projective coordinates (X:Z). -void sike_xTPL( - const point_proj_t P, point_proj_t Q, const f2elm_t A24minus, - const f2elm_t A24plus); -// Computes [3^e](X:Z) on Montgomery curve with projective constant -// via e repeated triplings. -void sike_xTPLe( - const point_proj_t P, point_proj_t Q, const f2elm_t A24minus, - const f2elm_t A24plus, size_t e); -// Given the x-coordinates of P, Q, and R, returns the value A -// corresponding to the Montgomery curve E_A: y^2=x^3+A*x^2+x such that R=Q-P on E_A. -void sike_get_A( - const f2elm_t xP, const f2elm_t xQ, const f2elm_t xR, f2elm_t A); -// Computes the j-invariant of a Montgomery curve with projective constant. -void sike_j_inv( - const f2elm_t A, const f2elm_t C, f2elm_t jinv); -// Computes the corresponding 4-isogeny of a projective Montgomery -// point (X4:Z4) of order 4. -void sike_get_4_isog( - const point_proj_t P, f2elm_t A24plus, f2elm_t C24, f2elm_t* coeff); -// Computes the corresponding 3-isogeny of a projective Montgomery -// point (X3:Z3) of order 3. -void sike_get_3_isog( - const point_proj_t P, f2elm_t A24minus, f2elm_t A24plus, - f2elm_t* coeff); -// Computes the 3-isogeny R=phi(X:Z), given projective point (X3:Z3) -// of order 3 on a Montgomery curve and a point P with coefficients given in coeff. -void sike_eval_3_isog( - point_proj_t Q, f2elm_t* coeff); -// Evaluates the isogeny at the point (X:Z) in the domain of the isogeny. -void sike_eval_4_isog( - point_proj_t P, f2elm_t* coeff); -// 3-way simultaneous inversion -void sike_inv_3_way( - f2elm_t z1, f2elm_t z2, f2elm_t z3); - -#endif // ISOGENY_H_ diff --git a/third_party/sike/sike.c b/third_party/sike/sike.c deleted file mode 100644 index 87b74174b4..0000000000 --- a/third_party/sike/sike.c +++ /dev/null @@ -1,531 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: supersingular isogeny key encapsulation (SIKE) protocol -*********************************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" -#include "isogeny.h" -#include "fpx.h" - -extern const struct params_t sike_params; - -// SIDH_JINV_BYTESZ is a number of bytes used for encoding j-invariant. -#define SIDH_JINV_BYTESZ 110U -// SIDH_PRV_A_BITSZ is a number of bits of SIDH private key (2-isogeny) -#define SIDH_PRV_A_BITSZ 216U -// SIDH_PRV_A_BITSZ is a number of bits of SIDH private key (3-isogeny) -#define SIDH_PRV_B_BITSZ 217U -// MAX_INT_POINTS_ALICE is a number of points used in 2-isogeny tree computation -#define MAX_INT_POINTS_ALICE 7U -// MAX_INT_POINTS_ALICE is a number of points used in 3-isogeny tree computation -#define MAX_INT_POINTS_BOB 8U - -// Swap points. -// If option = 0 then P <- P and Q <- Q, else if option = 0xFF...FF then P <- Q and Q <- P -#if !defined(OPENSSL_X86_64) || defined(OPENSSL_NO_ASM) -static void sike_cswap(point_proj_t P, point_proj_t Q, const crypto_word_t option) -{ - crypto_word_t temp; - for (size_t i = 0; i < NWORDS_FIELD; i++) { - temp = option & (P->X->c0[i] ^ Q->X->c0[i]); - P->X->c0[i] = temp ^ P->X->c0[i]; - Q->X->c0[i] = temp ^ Q->X->c0[i]; - temp = option & (P->Z->c0[i] ^ Q->Z->c0[i]); - P->Z->c0[i] = temp ^ P->Z->c0[i]; - Q->Z->c0[i] = temp ^ Q->Z->c0[i]; - temp = option & (P->X->c1[i] ^ Q->X->c1[i]); - P->X->c1[i] = temp ^ P->X->c1[i]; - Q->X->c1[i] = temp ^ Q->X->c1[i]; - temp = option & (P->Z->c1[i] ^ Q->Z->c1[i]); - P->Z->c1[i] = temp ^ P->Z->c1[i]; - Q->Z->c1[i] = temp ^ Q->Z->c1[i]; - } -} -#endif - -// Swap points. -// If option = 0 then P <- P and Q <- Q, else if option = 0xFF...FF then P <- Q and Q <- P -static inline void sike_fp2cswap(point_proj_t P, point_proj_t Q, const crypto_word_t option) -{ -#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) - sike_cswap_asm(P, Q, option); -#else - sike_cswap(P, Q, option); -#endif -} - -static void ladder3Pt( - const f2elm_t xP, const f2elm_t xQ, const f2elm_t xPQ, const uint8_t* m, - int is_A, point_proj_t R, const f2elm_t A) { - point_proj_t R0 = POINT_PROJ_INIT, R2 = POINT_PROJ_INIT; - f2elm_t A24 = F2ELM_INIT; - crypto_word_t mask; - int bit, swap, prevbit = 0; - - const size_t nbits = is_A?SIDH_PRV_A_BITSZ:SIDH_PRV_B_BITSZ; - - // Initializing constant - sike_fpcopy(sike_params.mont_one, A24[0].c0); - sike_fp2add(A24, A24, A24); - sike_fp2add(A, A24, A24); - sike_fp2div2(A24, A24); - sike_fp2div2(A24, A24); // A24 = (A+2)/4 - - // Initializing points - sike_fp2copy(xQ, R0->X); - sike_fpcopy(sike_params.mont_one, R0->Z[0].c0); - sike_fp2copy(xPQ, R2->X); - sike_fpcopy(sike_params.mont_one, R2->Z[0].c0); - sike_fp2copy(xP, R->X); - sike_fpcopy(sike_params.mont_one, R->Z[0].c0); - memset(R->Z->c1, 0, sizeof(R->Z->c1)); - - // Main loop - for (size_t i = 0; i < nbits; i++) { - bit = (m[i >> 3] >> (i & 7)) & 1; - swap = bit ^ prevbit; - prevbit = bit; - mask = 0 - (crypto_word_t)swap; - - sike_fp2cswap(R, R2, mask); - sike_xDBLADD(R0, R2, R->X, A24); - sike_fp2mul_mont(R2->X, R->Z, R2->X); - } - - mask = 0 - (crypto_word_t)prevbit; - sike_fp2cswap(R, R2, mask); -} - -// Initialization of basis points -static inline void sike_init_basis(const crypto_word_t *gen, f2elm_t XP, f2elm_t XQ, f2elm_t XR) { - sike_fpcopy(gen, XP->c0); - sike_fpcopy(gen + NWORDS_FIELD, XP->c1); - sike_fpcopy(gen + 2*NWORDS_FIELD, XQ->c0); - sike_fpcopy(gen + 3*NWORDS_FIELD, XQ->c1); - sike_fpcopy(gen + 4*NWORDS_FIELD, XR->c0); - sike_fpcopy(gen + 5*NWORDS_FIELD, XR->c1); -} - -// Conversion of GF(p^2) element from Montgomery to standard representation. -static inline void sike_fp2_encode(const f2elm_t x, uint8_t *enc) { - f2elm_t t; - sike_from_fp2mont(x, t); - - // convert to bytes in little endian form - for (size_t i=0; i> (8*(i%LSZ))) & 0xFF; - enc[i+FIELD_BYTESZ] = (t[0].c1[i/LSZ] >> (8*(i%LSZ))) & 0xFF; - } -} - -// Parse byte sequence back into GF(p^2) element, and conversion to Montgomery representation. -// Elements over GF(p503) are encoded in 63 octets in little endian format -// (i.e., the least significant octet is located in the lowest memory address). -static inline void fp2_decode(const uint8_t *enc, f2elm_t t) { - memset(t[0].c0, 0, sizeof(t[0].c0)); - memset(t[0].c1, 0, sizeof(t[0].c1)); - // convert bytes in little endian form to f2elm_t - for (size_t i = 0; i < FIELD_BYTESZ; i++) { - t[0].c0[i/LSZ] |= ((crypto_word_t)enc[i+ 0]) << (8*(i%LSZ)); - t[0].c1[i/LSZ] |= ((crypto_word_t)enc[i+FIELD_BYTESZ]) << (8*(i%LSZ)); - } - sike_to_fp2mont(t, t); -} - -// Alice's ephemeral public key generation -// Input: a private key prA in the range [0, 2^250 - 1], stored in 32 bytes. -// Output: the public key pkA consisting of 3 GF(p503^2) elements encoded in 378 bytes. -static void gen_iso_A(const uint8_t* skA, uint8_t* pkA) -{ - point_proj_t R, pts[MAX_INT_POINTS_ALICE]; - point_proj_t phiP = POINT_PROJ_INIT; - point_proj_t phiQ = POINT_PROJ_INIT; - point_proj_t phiR = POINT_PROJ_INIT; - f2elm_t XPA, XQA, XRA, coeff[3]; - f2elm_t A24plus = F2ELM_INIT; - f2elm_t C24 = F2ELM_INIT; - f2elm_t A = F2ELM_INIT; - unsigned int m, index = 0, pts_index[MAX_INT_POINTS_ALICE], npts = 0, ii = 0; - - // Initialize basis points - sike_init_basis(sike_params.A_gen, XPA, XQA, XRA); - sike_init_basis(sike_params.B_gen, phiP->X, phiQ->X, phiR->X); - sike_fpcopy(sike_params.mont_one, (phiP->Z)->c0); - sike_fpcopy(sike_params.mont_one, (phiQ->Z)->c0); - sike_fpcopy(sike_params.mont_one, (phiR->Z)->c0); - - // Initialize constants: A24plus = A+2C, C24 = 4C, where A=6, C=1 - sike_fpcopy(sike_params.mont_one, A24plus->c0); - sike_fp2add(A24plus, A24plus, A24plus); - sike_fp2add(A24plus, A24plus, C24); - sike_fp2add(A24plus, C24, A); - sike_fp2add(C24, C24, A24plus); - - // Retrieve kernel point - ladder3Pt(XPA, XQA, XRA, skA, 1, R, A); - - // Traverse tree - index = 0; - for (size_t row = 1; row < A_max; row++) { - while (index < A_max-row) { - sike_fp2copy(R->X, pts[npts]->X); - sike_fp2copy(R->Z, pts[npts]->Z); - pts_index[npts++] = index; - m = sike_params.A_strat[ii++]; - sike_xDBLe(R, R, A24plus, C24, (2*m)); - index += m; - } - sike_get_4_isog(R, A24plus, C24, coeff); - - for (size_t i = 0; i < npts; i++) { - sike_eval_4_isog(pts[i], coeff); - } - sike_eval_4_isog(phiP, coeff); - sike_eval_4_isog(phiQ, coeff); - sike_eval_4_isog(phiR, coeff); - - sike_fp2copy(pts[npts-1]->X, R->X); - sike_fp2copy(pts[npts-1]->Z, R->Z); - index = pts_index[npts-1]; - npts -= 1; - } - - sike_get_4_isog(R, A24plus, C24, coeff); - sike_eval_4_isog(phiP, coeff); - sike_eval_4_isog(phiQ, coeff); - sike_eval_4_isog(phiR, coeff); - - sike_inv_3_way(phiP->Z, phiQ->Z, phiR->Z); - sike_fp2mul_mont(phiP->X, phiP->Z, phiP->X); - sike_fp2mul_mont(phiQ->X, phiQ->Z, phiQ->X); - sike_fp2mul_mont(phiR->X, phiR->Z, phiR->X); - - // Format public key - sike_fp2_encode(phiP->X, pkA); - sike_fp2_encode(phiQ->X, pkA + SIDH_JINV_BYTESZ); - sike_fp2_encode(phiR->X, pkA + 2*SIDH_JINV_BYTESZ); -} - -// Bob's ephemeral key-pair generation -// It produces a private key skB and computes the public key pkB. -// The private key is an integer in the range [0, 2^Floor(Log(2,3^159)) - 1], stored in 32 bytes. -// The public key consists of 3 GF(p503^2) elements encoded in 378 bytes. -static void gen_iso_B(const uint8_t* skB, uint8_t* pkB) -{ - point_proj_t R, pts[MAX_INT_POINTS_BOB]; - point_proj_t phiP = POINT_PROJ_INIT; - point_proj_t phiQ = POINT_PROJ_INIT; - point_proj_t phiR = POINT_PROJ_INIT; - f2elm_t XPB, XQB, XRB, coeff[3]; - f2elm_t A24plus = F2ELM_INIT; - f2elm_t A24minus = F2ELM_INIT; - f2elm_t A = F2ELM_INIT; - unsigned int m, index = 0, pts_index[MAX_INT_POINTS_BOB], npts = 0, ii = 0; - - // Initialize basis points - sike_init_basis(sike_params.B_gen, XPB, XQB, XRB); - sike_init_basis(sike_params.A_gen, phiP->X, phiQ->X, phiR->X); - sike_fpcopy(sike_params.mont_one, (phiP->Z)->c0); - sike_fpcopy(sike_params.mont_one, (phiQ->Z)->c0); - sike_fpcopy(sike_params.mont_one, (phiR->Z)->c0); - - // Initialize constants: A24minus = A-2C, A24plus = A+2C, where A=6, C=1 - sike_fpcopy(sike_params.mont_one, A24plus->c0); - sike_fp2add(A24plus, A24plus, A24plus); - sike_fp2add(A24plus, A24plus, A24minus); - sike_fp2add(A24plus, A24minus, A); - sike_fp2add(A24minus, A24minus, A24plus); - - // Retrieve kernel point - ladder3Pt(XPB, XQB, XRB, skB, 0, R, A); - - // Traverse tree - index = 0; - for (size_t row = 1; row < B_max; row++) { - while (index < B_max-row) { - sike_fp2copy(R->X, pts[npts]->X); - sike_fp2copy(R->Z, pts[npts]->Z); - pts_index[npts++] = index; - m = sike_params.B_strat[ii++]; - sike_xTPLe(R, R, A24minus, A24plus, m); - index += m; - } - sike_get_3_isog(R, A24minus, A24plus, coeff); - - for (size_t i = 0; i < npts; i++) { - sike_eval_3_isog(pts[i], coeff); - } - sike_eval_3_isog(phiP, coeff); - sike_eval_3_isog(phiQ, coeff); - sike_eval_3_isog(phiR, coeff); - - sike_fp2copy(pts[npts-1]->X, R->X); - sike_fp2copy(pts[npts-1]->Z, R->Z); - index = pts_index[npts-1]; - npts -= 1; - } - - sike_get_3_isog(R, A24minus, A24plus, coeff); - sike_eval_3_isog(phiP, coeff); - sike_eval_3_isog(phiQ, coeff); - sike_eval_3_isog(phiR, coeff); - - sike_inv_3_way(phiP->Z, phiQ->Z, phiR->Z); - sike_fp2mul_mont(phiP->X, phiP->Z, phiP->X); - sike_fp2mul_mont(phiQ->X, phiQ->Z, phiQ->X); - sike_fp2mul_mont(phiR->X, phiR->Z, phiR->X); - - // Format public key - sike_fp2_encode(phiP->X, pkB); - sike_fp2_encode(phiQ->X, pkB + SIDH_JINV_BYTESZ); - sike_fp2_encode(phiR->X, pkB + 2*SIDH_JINV_BYTESZ); -} - -// Alice's ephemeral shared secret computation -// It produces a shared secret key ssA using her secret key skA and Bob's public key pkB -// Inputs: Alice's skA is an integer in the range [0, 2^250 - 1], stored in 32 bytes. -// Bob's pkB consists of 3 GF(p503^2) elements encoded in 378 bytes. -// Output: a shared secret ssA that consists of one element in GF(p503^2) encoded in 126 bytes. -static void ex_iso_A(const uint8_t* skA, const uint8_t* pkB, uint8_t* ssA) -{ - point_proj_t R, pts[MAX_INT_POINTS_ALICE]; - f2elm_t coeff[3], PKB[3], jinv; - f2elm_t A24plus = F2ELM_INIT; - f2elm_t C24 = F2ELM_INIT; - f2elm_t A = F2ELM_INIT; - unsigned int m, index = 0, pts_index[MAX_INT_POINTS_ALICE], npts = 0, ii = 0; - - // Initialize images of Bob's basis - fp2_decode(pkB, PKB[0]); - fp2_decode(pkB + SIDH_JINV_BYTESZ, PKB[1]); - fp2_decode(pkB + 2*SIDH_JINV_BYTESZ, PKB[2]); - - // Initialize constants - sike_get_A(PKB[0], PKB[1], PKB[2], A); - sike_fpadd(sike_params.mont_one, sike_params.mont_one, C24->c0); - sike_fp2add(A, C24, A24plus); - sike_fpadd(C24->c0, C24->c0, C24->c0); - - // Retrieve kernel point - ladder3Pt(PKB[0], PKB[1], PKB[2], skA, 1, R, A); - - // Traverse tree - index = 0; - for (size_t row = 1; row < A_max; row++) { - while (index < A_max-row) { - sike_fp2copy(R->X, pts[npts]->X); - sike_fp2copy(R->Z, pts[npts]->Z); - pts_index[npts++] = index; - m = sike_params.A_strat[ii++]; - sike_xDBLe(R, R, A24plus, C24, (2*m)); - index += m; - } - sike_get_4_isog(R, A24plus, C24, coeff); - - for (size_t i = 0; i < npts; i++) { - sike_eval_4_isog(pts[i], coeff); - } - - sike_fp2copy(pts[npts-1]->X, R->X); - sike_fp2copy(pts[npts-1]->Z, R->Z); - index = pts_index[npts-1]; - npts -= 1; - } - - sike_get_4_isog(R, A24plus, C24, coeff); - sike_fp2add(A24plus, A24plus, A24plus); - sike_fp2sub(A24plus, C24, A24plus); - sike_fp2add(A24plus, A24plus, A24plus); - sike_j_inv(A24plus, C24, jinv); - sike_fp2_encode(jinv, ssA); -} - -// Bob's ephemeral shared secret computation -// It produces a shared secret key ssB using his secret key skB and Alice's public key pkA -// Inputs: Bob's skB is an integer in the range [0, 2^Floor(Log(2,3^159)) - 1], stored in 32 bytes. -// Alice's pkA consists of 3 GF(p503^2) elements encoded in 378 bytes. -// Output: a shared secret ssB that consists of one element in GF(p503^2) encoded in 126 bytes. -static void ex_iso_B(const uint8_t* skB, const uint8_t* pkA, uint8_t* ssB) -{ - point_proj_t R, pts[MAX_INT_POINTS_BOB]; - f2elm_t coeff[3], PKB[3], jinv; - f2elm_t A24plus = F2ELM_INIT; - f2elm_t A24minus = F2ELM_INIT; - f2elm_t A = F2ELM_INIT; - unsigned int m, index = 0, pts_index[MAX_INT_POINTS_BOB], npts = 0, ii = 0; - - // Initialize images of Alice's basis - fp2_decode(pkA, PKB[0]); - fp2_decode(pkA + SIDH_JINV_BYTESZ, PKB[1]); - fp2_decode(pkA + 2*SIDH_JINV_BYTESZ, PKB[2]); - - // Initialize constants - sike_get_A(PKB[0], PKB[1], PKB[2], A); - sike_fpadd(sike_params.mont_one, sike_params.mont_one, A24minus->c0); - sike_fp2add(A, A24minus, A24plus); - sike_fp2sub(A, A24minus, A24minus); - - // Retrieve kernel point - ladder3Pt(PKB[0], PKB[1], PKB[2], skB, 0, R, A); - - // Traverse tree - index = 0; - for (size_t row = 1; row < B_max; row++) { - while (index < B_max-row) { - sike_fp2copy(R->X, pts[npts]->X); - sike_fp2copy(R->Z, pts[npts]->Z); - pts_index[npts++] = index; - m = sike_params.B_strat[ii++]; - sike_xTPLe(R, R, A24minus, A24plus, m); - index += m; - } - sike_get_3_isog(R, A24minus, A24plus, coeff); - - for (size_t i = 0; i < npts; i++) { - sike_eval_3_isog(pts[i], coeff); - } - - sike_fp2copy(pts[npts-1]->X, R->X); - sike_fp2copy(pts[npts-1]->Z, R->Z); - index = pts_index[npts-1]; - npts -= 1; - } - - sike_get_3_isog(R, A24minus, A24plus, coeff); - sike_fp2add(A24plus, A24minus, A); - sike_fp2add(A, A, A); - sike_fp2sub(A24plus, A24minus, A24plus); - sike_j_inv(A, A24plus, jinv); - sike_fp2_encode(jinv, ssB); -} - -int SIKE_keypair(uint8_t out_priv[SIKE_PRV_BYTESZ], - uint8_t out_pub[SIKE_PUB_BYTESZ]) { - int ret = 0; - - // Calculate private key for Alice. Needs to be in range [0, 2^0xFA - 1] and < - // 253 bits - BIGNUM *bn_sidh_prv = BN_new(); - if (!bn_sidh_prv || - !BN_rand(bn_sidh_prv, SIDH_PRV_B_BITSZ, BN_RAND_TOP_ONE, - BN_RAND_BOTTOM_ANY) || - !BN_bn2le_padded(out_priv, BITS_TO_BYTES(SIDH_PRV_B_BITSZ), - bn_sidh_prv)) { - goto end; - } - - gen_iso_B(out_priv, out_pub); - ret = 1; - -end: - BN_free(bn_sidh_prv); - return ret; -} - -void SIKE_encaps(uint8_t out_shared_key[SIKE_SS_BYTESZ], - uint8_t out_ciphertext[SIKE_CT_BYTESZ], - const uint8_t pub_key[SIKE_PUB_BYTESZ]) { - // Secret buffer is reused by the function to store some ephemeral - // secret data. It's size must be maximum of SHA256_CBLOCK, - // SIKE_MSG_BYTESZ and SIDH_PRV_A_BITSZ in bytes. - uint8_t secret[SHA256_CBLOCK]; - uint8_t j[SIDH_JINV_BYTESZ]; - uint8_t temp[SIKE_MSG_BYTESZ + SIKE_CT_BYTESZ]; - SHA256_CTX ctx; - - // Generate secret key for A - // secret key A = SHA256({0,1}^n || pub_key)) mod SIDH_PRV_A_BITSZ - RAND_bytes(temp, SIKE_MSG_BYTESZ); - - SHA256_Init(&ctx); - SHA256_Update(&ctx, temp, SIKE_MSG_BYTESZ); - SHA256_Update(&ctx, pub_key, SIKE_PUB_BYTESZ); - SHA256_Final(secret, &ctx); - - // Generate public key for A - first part of the ciphertext - gen_iso_A(secret, out_ciphertext); - - // Generate c1: - // h = SHA256(j-invariant) - // c1 = h ^ m - ex_iso_A(secret, pub_key, j); - SHA256_Init(&ctx); - SHA256_Update(&ctx, j, sizeof(j)); - SHA256_Final(secret, &ctx); - - // c1 = h ^ m - uint8_t *c1 = &out_ciphertext[SIKE_PUB_BYTESZ]; - for (size_t i = 0; i < SIKE_MSG_BYTESZ; i++) { - c1[i] = temp[i] ^ secret[i]; - } - - SHA256_Init(&ctx); - SHA256_Update(&ctx, temp, SIKE_MSG_BYTESZ); - SHA256_Update(&ctx, out_ciphertext, SIKE_CT_BYTESZ); - SHA256_Final(secret, &ctx); - // Generate shared secret out_shared_key = SHA256(m||out_ciphertext) - memcpy(out_shared_key, secret, SIKE_SS_BYTESZ); -} - -void SIKE_decaps(uint8_t out_shared_key[SIKE_SS_BYTESZ], - const uint8_t ciphertext[SIKE_CT_BYTESZ], - const uint8_t pub_key[SIKE_PUB_BYTESZ], - const uint8_t priv_key[SIKE_PRV_BYTESZ]) { - // Secret buffer is reused by the function to store some ephemeral - // secret data. It's size must be maximum of SHA256_CBLOCK, - // SIKE_MSG_BYTESZ and SIDH_PRV_A_BITSZ in bytes. - uint8_t secret[SHA256_CBLOCK]; - uint8_t j[SIDH_JINV_BYTESZ]; - uint8_t c0[SIKE_PUB_BYTESZ]; - uint8_t temp[SIKE_MSG_BYTESZ]; - uint8_t shared_nok[SIKE_MSG_BYTESZ]; - SHA256_CTX ctx; - - // This is OK as we are only using ephemeral keys in BoringSSL - RAND_bytes(shared_nok, SIKE_MSG_BYTESZ); - - // Recover m - // Let ciphertext = c0 || c1 - both have fixed sizes - // m = F(j-invariant(c0, priv_key)) ^ c1 - ex_iso_B(priv_key, ciphertext, j); - - SHA256_Init(&ctx); - SHA256_Update(&ctx, j, sizeof(j)); - SHA256_Final(secret, &ctx); - - const uint8_t *c1 = &ciphertext[sizeof(c0)]; - for (size_t i = 0; i < SIKE_MSG_BYTESZ; i++) { - temp[i] = c1[i] ^ secret[i]; - } - - SHA256_Init(&ctx); - SHA256_Update(&ctx, temp, SIKE_MSG_BYTESZ); - SHA256_Update(&ctx, pub_key, SIKE_PUB_BYTESZ); - SHA256_Final(secret, &ctx); - - // Recover c0 = public key A - gen_iso_A(secret, c0); - crypto_word_t ok = constant_time_is_zero_w( - CRYPTO_memcmp(c0, ciphertext, SIKE_PUB_BYTESZ)); - for (size_t i = 0; i < SIKE_MSG_BYTESZ; i++) { - temp[i] = constant_time_select_8(ok, temp[i], shared_nok[i]); - } - - SHA256_Init(&ctx); - SHA256_Update(&ctx, temp, SIKE_MSG_BYTESZ); - SHA256_Update(&ctx, ciphertext, SIKE_CT_BYTESZ); - SHA256_Final(secret, &ctx); - - // Generate shared secret out_shared_key = SHA256(m||ciphertext) - memcpy(out_shared_key, secret, SIKE_SS_BYTESZ); -} diff --git a/third_party/sike/sike.h b/third_party/sike/sike.h deleted file mode 100644 index 5819ebf4df..0000000000 --- a/third_party/sike/sike.h +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: API header file for SIKE -*********************************************************************************************/ - -#ifndef SIKE_H_ -#define SIKE_H_ - -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/* SIKE - * - * SIKE is a isogeny based post-quantum key encapsulation mechanism. Description of the - * algorithm is provided in [SIKE]. This implementation uses 434-bit field size. The code - * is based on "Additional_Implementations" from PQC NIST submission package which can - * be found here: - * https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents/round-1/submissions/SIKE.zip - * - * [SIKE] https://sike.org/files/SIDH-spec.pdf - */ - -// SIKE_PUB_BYTESZ is the number of bytes in a public key. -#define SIKE_PUB_BYTESZ 330 -// SIKE_PRV_BYTESZ is the number of bytes in a private key. -#define SIKE_PRV_BYTESZ 28 -// SIKE_SS_BYTESZ is the number of bytes in a shared key. -#define SIKE_SS_BYTESZ 16 -// SIKE_MSG_BYTESZ is the number of bytes in a random bit string concatenated -// with the public key (see 1.4 of SIKE). -#define SIKE_MSG_BYTESZ 16 -// SIKE_SS_BYTESZ is the number of bytes in a ciphertext. -#define SIKE_CT_BYTESZ (SIKE_PUB_BYTESZ + SIKE_MSG_BYTESZ) - -// SIKE_keypair outputs a public and secret key. Internally it uses BN_rand() as -// an entropy source. In case of success function returns 1, otherwise 0. -OPENSSL_EXPORT int SIKE_keypair( - uint8_t out_priv[SIKE_PRV_BYTESZ], - uint8_t out_pub[SIKE_PUB_BYTESZ]); - -// SIKE_encaps generates and encrypts a random session key, writing those values to -// |out_shared_key| and |out_ciphertext|, respectively. -OPENSSL_EXPORT void SIKE_encaps( - uint8_t out_shared_key[SIKE_SS_BYTESZ], - uint8_t out_ciphertext[SIKE_CT_BYTESZ], - const uint8_t pub_key[SIKE_PUB_BYTESZ]); - -// SIKE_decaps outputs a random session key, writing it to |out_shared_key|. -OPENSSL_EXPORT void SIKE_decaps( - uint8_t out_shared_key[SIKE_SS_BYTESZ], - const uint8_t ciphertext[SIKE_CT_BYTESZ], - const uint8_t pub_key[SIKE_PUB_BYTESZ], - const uint8_t priv_key[SIKE_PRV_BYTESZ]); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/third_party/sike/sike_test.cc b/third_party/sike/sike_test.cc deleted file mode 100644 index 2180a52892..0000000000 --- a/third_party/sike/sike_test.cc +++ /dev/null @@ -1,251 +0,0 @@ -/* Copyright (c) 2018, Google 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. */ - -#include -#include - -#include "sike.h" -#include "fpx.h" -#include "../../crypto/test/abi_test.h" - -TEST(SIKE, RoundTrip) { - uint8_t sk[SIKE_PRV_BYTESZ] = {0}; - uint8_t pk[SIKE_PUB_BYTESZ] = {0}; - uint8_t ct[SIKE_CT_BYTESZ] = {0}; - uint8_t ss_enc[SIKE_SS_BYTESZ] = {0}; - uint8_t ss_dec[SIKE_SS_BYTESZ] = {0}; - - for (size_t i = 0; i < 30; i++) { - EXPECT_EQ(SIKE_keypair(sk, pk), 1); - SIKE_encaps(ss_enc, ct, pk); - SIKE_decaps(ss_dec, ct, pk, sk); - - EXPECT_EQ(memcmp(ss_enc, ss_dec, SIKE_SS_BYTESZ), 0); - } -} - -TEST(SIKE, Decapsulation) { - const uint8_t sk[SIKE_PRV_BYTESZ] = { - 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}; - - const uint8_t pk[SIKE_PUB_BYTESZ] = { - 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}; - - const uint8_t ct[SIKE_CT_BYTESZ] = { - 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}; - - const uint8_t ss_exp[SIKE_SS_BYTESZ] = {0xA1, 0xF9, 0x5A, 0x67, 0xB9, 0x3D, - 0x1E, 0x72, 0xE8, 0xC5, 0x71, 0xF1, - 0x4C, 0xB2, 0xAA, 0x6D}; - - uint8_t ss_dec[SIKE_SS_BYTESZ] = {0}; - SIKE_decaps(ss_dec, ct, pk, sk); - EXPECT_EQ(memcmp(ss_dec, ss_exp, sizeof(ss_exp)), 0); -} - -// SIKE_encaps and SIKE_keypair doesn't return zeros. -TEST(SIKE, NonZero) { - uint8_t sk[SIKE_PRV_BYTESZ] = {0}; - uint8_t pk[SIKE_PUB_BYTESZ] = {0}; - uint8_t ct[SIKE_CT_BYTESZ] = {0}; - uint8_t ss[SIKE_SS_BYTESZ] = {0}; - - // Check secret and public key returned by SIKE_keypair - EXPECT_EQ(SIKE_keypair(sk, pk), 1); - uint8_t tmp = 0; - for (size_t i = 0; i < sizeof(sk); i++) { - tmp |= sk[i]; - } - EXPECT_NE(tmp, 0); - - tmp = 0; - for (size_t i = 0; i < sizeof(pk); i++) { - tmp |= pk[i]; - } - EXPECT_NE(tmp, 0); - - // Check shared secret and ciphertext returned by SIKE_encaps - SIKE_encaps(ss, ct, pk); - tmp = 0; - for (size_t i = 0; i < sizeof(ct); i++) { - tmp |= ct[i]; - } - EXPECT_NE(tmp, 0); - - tmp = 0; - for (size_t i = 0; i < sizeof(ss); i++) { - tmp |= ss[i]; - } - EXPECT_NE(tmp, 0); -} - -TEST(SIKE, Negative) { - uint8_t sk[SIKE_PRV_BYTESZ] = {0}; - uint8_t pk[SIKE_PUB_BYTESZ] = {0}; - uint8_t ct[SIKE_CT_BYTESZ] = {0}; - uint8_t ss_enc[SIKE_SS_BYTESZ] = {0}; - uint8_t ss_dec[SIKE_SS_BYTESZ] = {0}; - - EXPECT_EQ(SIKE_keypair(sk, pk), 1); - SIKE_encaps(ss_enc, ct, pk); - - // Change cipertext - uint8_t ct_tmp[SIKE_CT_BYTESZ] = {0}; - memcpy(ct_tmp, ct, sizeof(ct)); - ct_tmp[0] = ~ct_tmp[0]; - SIKE_decaps(ss_dec, ct_tmp, pk, sk); - EXPECT_NE(memcmp(ss_enc, ss_dec, SIKE_SS_BYTESZ), 0); - - // Change secret key - uint8_t sk_tmp[SIKE_PRV_BYTESZ] = {0}; - memcpy(sk_tmp, sk, sizeof(sk)); - sk_tmp[0] = ~sk_tmp[0]; - SIKE_decaps(ss_dec, ct, pk, sk_tmp); - EXPECT_NE(memcmp(ss_enc, ss_dec, SIKE_SS_BYTESZ), 0); - - // Change public key - uint8_t pk_tmp[SIKE_PUB_BYTESZ] = {0}; - memcpy(pk_tmp, pk, sizeof(pk)); - pk_tmp[0] = ~pk_tmp[0]; - SIKE_decaps(ss_dec, ct, pk_tmp, sk); - EXPECT_NE(memcmp(ss_enc, ss_dec, SIKE_SS_BYTESZ), 0); -} - -TEST(SIKE, Unaligned) { - alignas(4) uint8_t priv[SIKE_PRV_BYTESZ + 1]; - alignas(4) uint8_t pub[SIKE_PUB_BYTESZ + 1]; - alignas(4) uint8_t shared_key1[SIKE_SS_BYTESZ + 1]; - alignas(4) uint8_t ciphertext[SIKE_CT_BYTESZ + 1]; - alignas(4) uint8_t shared_key2[SIKE_SS_BYTESZ + 1]; - - ASSERT_TRUE(SIKE_keypair(priv + 1, pub + 1)); - SIKE_encaps(shared_key1 + 1, ciphertext + 1, pub + 1); - SIKE_decaps(shared_key2 + 1, ciphertext + 1, pub + 1, priv + 1); - - EXPECT_EQ(memcmp(shared_key1 + 1, shared_key2 + 1, SIKE_SS_BYTESZ), 0); -} - -#if defined(SUPPORTS_ABI_TEST) && \ - (defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)) -TEST(SIKE, ABI) { - felm_t a, b, c; - dfelm_t d, e, f; - CHECK_ABI(sike_fpadd, a, b, c); - CHECK_ABI(sike_fpsub, a, b, c); - CHECK_ABI(sike_mpmul, a, b, d); - CHECK_ABI(sike_fprdc, d, a); - CHECK_ABI(sike_mpadd_asm, a, b, c); - CHECK_ABI(sike_mpsubx2_asm, d, e, f); - CHECK_ABI(sike_mpdblsubx2_asm, d, e, f); -} - -// Additional tests for checking if assembly implementation -// of MUL and REDC handles carry chains correctly. -TEST(SIKE, CarryChains) { - // Expected results - const dfelm_t exp_mul = { - 0x0000000000000001, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, - 0x0000000000000000, 0xFFFFFFFFFFFFFFFE, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - }; - - const felm_t exp_redc = { - 0x93AA0C8C2D3235BE, 0xA8CD35DDDE399B46, 0xB9BBA5469509CA65, - 0x6B2FB3A5A2FB86E4, 0x585591BA6DBE862C, 0xD92D3FF5FE0938F2, - 0x0001E1F0EE75A1E1 - }; - - // Input - dfelm_t in14 = { - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF - }; - - felm_t in7 = { - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, - 0xFFFFFFFFFFFFFFFF - }; - - dfelm_t res; - sike_mpmul(in7, in7, res); - EXPECT_EQ(memcmp(exp_mul, res, sizeof(exp_mul)), 0); - - // modifies in14 and in7 - sike_fprdc(in14, in7); - EXPECT_EQ(memcmp(exp_redc, in7, sizeof(exp_redc)), 0); -} -#endif // SUPPORTS_ABI_TEST && (X86_64 || AARCH64) diff --git a/third_party/sike/utils.h b/third_party/sike/utils.h deleted file mode 100644 index bc806da01a..0000000000 --- a/third_party/sike/utils.h +++ /dev/null @@ -1,145 +0,0 @@ -/******************************************************************************************** -* SIDH: an efficient supersingular isogeny cryptography library -* -* Abstract: internal header file for P434 -*********************************************************************************************/ - -#ifndef UTILS_H_ -#define UTILS_H_ - -#include - -#include "../../crypto/internal.h" -#include "sike.h" - -// Conversion macro from number of bits to number of bytes -#define BITS_TO_BYTES(nbits) (((nbits)+7)/8) - -// Bit size of the field -#define BITS_FIELD 434 -// Byte size of the field -#define FIELD_BYTESZ BITS_TO_BYTES(BITS_FIELD) -// Number of 64-bit words of a 224-bit element -#define NBITS_ORDER 224 -#define NWORDS64_ORDER ((NBITS_ORDER+63)/64) -// Number of elements in Alice's strategy -#define A_max 108 -// Number of elements in Bob's strategy -#define B_max 137 -// Word size size -#define RADIX sizeof(crypto_word_t)*8 -// Byte size of a limb -#define LSZ sizeof(crypto_word_t) - -#if defined(OPENSSL_64_BIT) - // Number of words of a 434-bit field element - #define NWORDS_FIELD 7 - // Number of "0" digits in the least significant part of p434 + 1 - #define ZERO_WORDS 3 - // U64_TO_WORDS expands |x| for a |crypto_word_t| array literal. - #define U64_TO_WORDS(x) UINT64_C(x) -#else - // Number of words of a 434-bit field element - #define NWORDS_FIELD 14 - // Number of "0" digits in the least significant part of p434 + 1 - #define ZERO_WORDS 6 - // U64_TO_WORDS expands |x| for a |crypto_word_t| array literal. - #define U64_TO_WORDS(x) \ - (uint32_t)(UINT64_C(x) & 0xffffffff), (uint32_t)(UINT64_C(x) >> 32) -#endif - -// Extended datatype support -#if !defined(BORINGSSL_HAS_UINT128) - typedef uint64_t uint128_t[2]; -#endif - -// The following functions return 1 (TRUE) if condition is true, 0 (FALSE) otherwise -// Digit multiplication -#define MUL(multiplier, multiplicand, hi, lo) digit_x_digit((multiplier), (multiplicand), &(lo)); - -// If mask |x|==0xff.ff set |x| to 1, otherwise 0 -#define M2B(x) ((x)>>(RADIX-1)) - -// Digit addition with carry -#define ADDC(carryIn, addend1, addend2, carryOut, sumOut) \ -do { \ - crypto_word_t tempReg = (addend1) + (crypto_word_t)(carryIn); \ - (sumOut) = (addend2) + tempReg; \ - (carryOut) = M2B(constant_time_lt_w(tempReg, (crypto_word_t)(carryIn)) | \ - constant_time_lt_w((sumOut), tempReg)); \ -} while(0) - -// Digit subtraction with borrow -#define SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \ -do { \ - crypto_word_t tempReg = (minuend) - (subtrahend); \ - crypto_word_t borrowReg = M2B(constant_time_lt_w((minuend), (subtrahend))); \ - borrowReg |= ((borrowIn) & constant_time_is_zero_w(tempReg)); \ - (differenceOut) = tempReg - (crypto_word_t)(borrowIn); \ - (borrowOut) = borrowReg; \ -} while(0) - -/* Old GCC 4.9 (jessie) doesn't implement {0} initialization properly, - which violates C11 as described in 6.7.9, 21 (similarily C99, 6.7.8). - Defines below are used to work around the bug, and provide a way - to initialize f2elem_t and point_proj_t structs. - Bug has been fixed in GCC6 (debian stretch). -*/ -#define F2ELM_INIT {{ {0}, {0} }} -#define POINT_PROJ_INIT {{ F2ELM_INIT, F2ELM_INIT }} - -// Datatype for representing 434-bit field elements (448-bit max.) -// Elements over GF(p434) are encoded in 63 octets in little endian format -// (i.e., the least significant octet is located in the lowest memory address). -typedef crypto_word_t felm_t[NWORDS_FIELD]; - -// An element in F_{p^2}, is composed of two coefficients from F_p, * i.e. -// Fp2 element = c0 + c1*i in F_{p^2} -// Datatype for representing double-precision 2x434-bit field elements (448-bit max.) -// Elements (a+b*i) over GF(p434^2), where a and b are defined over GF(p434), are -// encoded as {a, b}, with a in the lowest memory portion. -typedef struct { - felm_t c0; - felm_t c1; -} fp2; - -// Our F_{p^2} element type is a pointer to the struct. -typedef fp2 f2elm_t[1]; - -// Datatype for representing double-precision 2x434-bit -// field elements in contiguous memory. -typedef crypto_word_t dfelm_t[2*NWORDS_FIELD]; - -// Constants used during SIKE computation. -struct params_t { - // Stores a prime - const crypto_word_t prime[NWORDS_FIELD]; - // Stores prime + 1 - const crypto_word_t prime_p1[NWORDS_FIELD]; - // Stores prime * 2 - const crypto_word_t prime_x2[NWORDS_FIELD]; - // Alice's generator values {XPA0 + XPA1*i, XQA0 + XQA1*i, XRA0 + XRA1*i} - // in GF(prime^2), expressed in Montgomery representation - const crypto_word_t A_gen[6*NWORDS_FIELD]; - // Bob's generator values {XPB0 + XPB1*i, XQB0 + XQB1*i, XRB0 + XRB1*i} - // in GF(prime^2), expressed in Montgomery representation - const crypto_word_t B_gen[6*NWORDS_FIELD]; - // Montgomery constant mont_R2 = (2^448)^2 mod prime - const crypto_word_t mont_R2[NWORDS_FIELD]; - // Value 'one' in Montgomery representation - const crypto_word_t mont_one[NWORDS_FIELD]; - // Value '6' in Montgomery representation - const crypto_word_t mont_six[NWORDS_FIELD]; - // Fixed parameters for isogeny tree computation - const unsigned int A_strat[A_max-1]; - const unsigned int B_strat[B_max-1]; -}; - -// Point representation in projective XZ Montgomery coordinates. -typedef struct { - f2elm_t X; - f2elm_t Z; -} point_proj; -typedef point_proj point_proj_t[1]; - -#endif // UTILS_H_ diff --git a/tool/speed.cc b/tool/speed.cc index 68073a99f6..224a72bdcc 100644 --- a/tool/speed.cc +++ b/tool/speed.cc @@ -52,8 +52,6 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) #include "../crypto/internal.h" #include "internal.h" -#include "../third_party/sike/sike.h" - // g_print_json is true if printed output is JSON formatted. static bool g_print_json = false; @@ -338,64 +336,6 @@ static bool SpeedRSAKeyGen(const std::string &selected) { return true; } -static bool SpeedSIKEP434(const std::string &selected) { - if (!selected.empty() && selected.find("SIKE") == std::string::npos) { - return true; - } - // speed generation - uint8_t public_SIKE[SIKE_PUB_BYTESZ]; - uint8_t private_SIKE[SIKE_PRV_BYTESZ]; - uint8_t ct[SIKE_CT_BYTESZ]; - bool res; - - { - TimeResults results; - res = TimeFunction(&results, - [&private_SIKE, &public_SIKE]() -> bool { - return (SIKE_keypair(private_SIKE, public_SIKE) == 1); - }); - results.Print("SIKE/P434 generate"); - } - - if (!res) { - fprintf(stderr, "Failed to time SIKE_keypair.\n"); - return false; - } - - { - TimeResults results; - TimeFunction(&results, - [&ct, &public_SIKE]() -> bool { - uint8_t ss[SIKE_SS_BYTESZ]; - SIKE_encaps(ss, ct, public_SIKE); - return true; - }); - results.Print("SIKE/P434 encap"); - } - - if (!res) { - fprintf(stderr, "Failed to time SIKE_encaps.\n"); - return false; - } - - { - TimeResults results; - TimeFunction(&results, - [&ct, &public_SIKE, &private_SIKE]() -> bool { - uint8_t ss[SIKE_SS_BYTESZ]; - SIKE_decaps(ss, ct, public_SIKE, private_SIKE); - return true; - }); - results.Print("SIKE/P434 decap"); - } - - if (!res) { - fprintf(stderr, "Failed to time SIKE_decaps.\n"); - return false; - } - return true; -} - static uint8_t *align(uint8_t *in, unsigned alignment) { return reinterpret_cast( (reinterpret_cast(in) + alignment) & @@ -1128,7 +1068,6 @@ bool Speed(const std::vector &args) { !SpeedECDH(selected) || !SpeedECDSA(selected) || !Speed25519(selected) || - !SpeedSIKEP434(selected) || !SpeedSPAKE2(selected) || !SpeedScrypt(selected) || !SpeedRSAKeyGen(selected) || diff --git a/util/generate_build_files.py b/util/generate_build_files.py index 8a5df75d76..6bd3abc645 100644 --- a/util/generate_build_files.py +++ b/util/generate_build_files.py @@ -640,8 +640,7 @@ def ExtractVariablesFromCMakeFile(cmakefile): def main(platforms): cmake = ExtractVariablesFromCMakeFile(os.path.join('src', 'sources.cmake')) crypto_c_files = (FindCFiles(os.path.join('src', 'crypto'), NoTestsNorFIPSFragments) + - FindCFiles(os.path.join('src', 'third_party', 'fiat'), NoTestsNorFIPSFragments) + - FindCFiles(os.path.join('src', 'third_party', 'sike'), NoTestsNorFIPSFragments)) + FindCFiles(os.path.join('src', 'third_party', 'fiat'), NoTestsNorFIPSFragments)) fips_fragments = FindCFiles(os.path.join('src', 'crypto', 'fipsmodule'), OnlyFIPSFragments) ssl_source_files = FindCFiles(os.path.join('src', 'ssl'), NoTests) tool_c_files = FindCFiles(os.path.join('src', 'tool'), NoTests) @@ -721,8 +720,7 @@ def NotSSLHeaderFiles(path, filename, is_dir): ssl_internal_h_files = FindHeaderFiles(os.path.join('src', 'ssl'), NoTests) crypto_internal_h_files = ( FindHeaderFiles(os.path.join('src', 'crypto'), NoTests) + - FindHeaderFiles(os.path.join('src', 'third_party', 'fiat'), NoTests) + - FindHeaderFiles(os.path.join('src', 'third_party', 'sike'), NoTests)) + FindHeaderFiles(os.path.join('src', 'third_party', 'fiat'), NoTests)) files = { 'bcm_crypto': bcm_crypto_c_files,