Commit 1f480b0f authored by Mike Hamburg's avatar Mike Hamburg
Browse files

Big changes for curve flexibility. For details see HISTORY.txt.

Very experimental Ed480-Ridinghood support is now in.  It's not fully optimized,
but in general the current build is 8-15% slower than Goldilocks.  It only works on
arch_x86_64, though arch_ref64 support ought to be easy.  Support on other arches
will be trickier, which is of course why I chose Goldilocks over Ridinghood in the
first place.

Next up, E-521.  Hopefully.

The code is starting to get spread out over a lot of files.  Some are per field*arch,
some per field, some per curve, some global.  It's hard to do much about this, though,
with a rather ugly .c.inc system.

There's currently no way to make a Ridinghood eBAT.  In fact, I haven't tested eBAT
support in this commit.  I also haven't tested NEON, but at least ARCH_32 works on
Intel.
parent edc6afe4
October 23, 2014:
Pushing through changes for curve flexibility. First up is
Ed480-Ridinghood, because it has the same number of words. Next
is E-521.
Experimental support for Ed480-Ridinghood. To use, compile with
make ... FIELD=p480 -XCFLAGS=-DGOLDI_FIELD_BITS=480
I still need to figure out what to do about the fact that the library
is called "goldilocks", but in will soon support curves that are not
ed448-goldilocks, at least experimentally.
Currently the whole system's header "goldilocks.h" doesn't have
a simpler way to override field size, but it does work (as a hack)
with -DGOLDI_FIELD_BITS=...
There is no support yet for coexistence of multiple fields in one
library. The field routines will have unique names, but scalarmul*
won't, and the top-level goldilocks routines have fixed names.
Current timings on Haswell:
Goldilocks: 178kcy keygen, 536kcy ecdh
Ridinghood: 193kcy keygen, 617kcy ecdh
Note that Ridinghood ECDH does worse than 480/448. This is at least
in part because I haven't calculated the overflow handling limits yet
in ec_point.h (this is a disadvantage of dropping the automated
tool for generating that file). So I'm reducing much more often
than I need to. (There's a really loud TODO in ec_point.h for that.)
Also, I haven't tested the limits on these reductions in a while, so
it could be that there are actual (security-critical) bugs in this
area, at least for p448. Now that there's field flexibility, it's
probably a good idea to make a field impl with extra words to check
this.
Furthermore, field_mulw_scc will perform differently on these two
curves based on whether the curve constant is positive or negative.
I should probably go optimize the "hot" routines like montgomery_step
to have separate cases for positive and negative.
September 29, 2014:
Yesterday I put in some more architecture detection, but it should
really be based on the arch directory, because what's in there really
......
......@@ -20,12 +20,13 @@ else
ARCH ?= arch_arm_32
endif
FIELD ?= p448
WARNFLAGS = -pedantic -Wall -Wextra -Werror -Wunreachable-code \
-Wmissing-declarations -Wunused-function -Wno-overlength-strings $(EXWARN)
INCFLAGS = -Isrc/include -Iinclude -Isrc/$(ARCH)
INCFLAGS = -Isrc/include -Iinclude -Isrc/$(FIELD) -Isrc/$(FIELD)/$(ARCH)
LANGFLAGS = -std=c99 -fno-strict-aliasing
GENFLAGS = -ffunction-sections -fdata-sections -fvisibility=hidden -fomit-frame-pointer -fPIC
OFLAGS = -O3
......@@ -63,7 +64,8 @@ ASFLAGS = $(ARCHFLAGS)
HEADERS= Makefile $(shell find . -name "*.h") build/timestamp
LIBCOMPONENTS= build/goldilocks.o build/barrett_field.o build/crandom.o \
build/p448.o build/ec_point.o build/scalarmul.o build/sha512.o build/magic.o build/arithmetic.o
build/$(FIELD).o build/ec_point.o build/scalarmul.o build/sha512.o build/magic.o \
build/f_arithmetic.o build/arithmetic.o
TESTCOMPONENTS=build/test.o build/test_scalarmul.o build/test_sha512.o \
build/test_pointops.o build/test_arithmetic.o build/test_goldilocks.o build/magic.o
......@@ -113,7 +115,10 @@ build/%.s: src/%.c $(HEADERS)
build/%.s: test/%.c $(HEADERS)
$(CC) $(CFLAGS) -S -c -o $@ $<
build/%.s: src/$(ARCH)/%.c $(HEADERS)
build/%.s: src/$(FIELD)/$(ARCH)/%.c $(HEADERS)
$(CC) $(CFLAGS) -S -c -o $@ $<
build/%.s: src/$(FIELD)/%.c $(HEADERS)
$(CC) $(CFLAGS) -S -c -o $@ $<
doc/timestamp:
......@@ -131,7 +136,7 @@ $(BATNAME): include/* src/* src/*/* test/batarch.map
targ="$@/crypto_$$prim/ed448goldilocks"; \
(while read arch where; do \
mkdir -p $$targ/`basename $$arch`; \
cp include/*.h src/*.c src/include/*.h src/bat/$$prim.c src/$$where/*.c src/$$where/*.h $$targ/`basename $$arch`; \
cp include/*.h src/*.c src/include/*.h src/bat/$$prim.c src/p448/$$where/*.c src/p448/$$where/*.h src/p448/*.c src/p448/*.h $$targ/`basename $$arch`; \
cp src/bat/api_$$prim.h $$targ/`basename $$arch`/api.h; \
perl -p -i -e 's/.*endif.*GOLDILOCKS_CONFIG_H/#define SUPERCOP_WONT_LET_ME_OPEN_FILES 1\n\n$$&/' $$targ/`basename $$arch`/config.h; \
perl -p -i -e 's/SYSNAME/'`basename $(BATNAME)`_`basename $$arch`'/g' $$targ/`basename $$arch`/api.h; \
......
......@@ -22,14 +22,18 @@
#define GOLDI_IMPLEMENT_SIGNATURES 1
#endif
/** The size of the Goldilocks field, in bits. */
/** The size of the Goldilocks field, in bits.
* Ifdef'd so you can override when testing experimental Ed480-Ridinghood or E-521.
*/
#ifndef GOLDI_FIELD_BITS
#define GOLDI_FIELD_BITS 448
#endif
/** The size of the Goldilocks scalars, in bits. */
#define GOLDI_SCALAR_BITS 446
#define GOLDI_SCALAR_BITS (GOLDI_FIELD_BITS-2)
/** The same size, in bytes. */
#define GOLDI_FIELD_BYTES (GOLDI_FIELD_BITS/8)
#define GOLDI_FIELD_BYTES ((GOLDI_FIELD_BITS+7)/8)
/** The size of a Goldilocks public key, in bytes. */
#define GOLDI_PUBLIC_KEY_BYTES GOLDI_FIELD_BYTES
......
/* Copyright (c) 2014 Cryptography Research, Inc.
* Released under the MIT License. See LICENSE.txt for license information.
*/
/**
* @file goldilocks.h
* @author Mike Hamburg
* @brief Goldilocks high-level functions.
*/
#ifndef __GOLDILOCKS_H__
#define __GOLDILOCKS_H__ 1
#include <stdint.h>
#ifndef GOLDI_IMPLEMENT_PRECOMPUTED_KEYS
/** If nonzero, implement precomputation for verify and ECDH. */
#define GOLDI_IMPLEMENT_PRECOMPUTED_KEYS 1
#endif
#ifndef GOLDI_IMPLEMENT_SIGNATURES
/** If nonzero, implement signatures. */
#define GOLDI_IMPLEMENT_SIGNATURES 1
#endif
/** The size of the Goldilocks field, in bits. */
#define GOLDI_FIELD_BITS 448
/** The size of the Goldilocks scalars, in bits. */
#define GOLDI_SCALAR_BITS 446
/** The same size, in bytes. */
#define GOLDI_FIELD_BYTES (GOLDI_FIELD_BITS/8)
/** The size of a Goldilocks public key, in bytes. */
#define GOLDI_PUBLIC_KEY_BYTES GOLDI_FIELD_BYTES
/** The extra bytes in a Goldilocks private key for the symmetric key. */
#define GOLDI_SYMKEY_BYTES 32
/** The size of a shared secret. */
#define GOLDI_SHARED_SECRET_BYTES 64
/** The size of a Goldilocks private key, in bytes. */
#define GOLDI_PRIVATE_KEY_BYTES (2*GOLDI_FIELD_BYTES + GOLDI_SYMKEY_BYTES)
/** The size of a Goldilocks signature, in bytes. */
#define GOLDI_SIGNATURE_BYTES (2*GOLDI_FIELD_BYTES)
/**
* @brief Serialized form of a Goldilocks public key.
*
* @warning This isn't even my final form!
*/
struct goldilocks_public_key_t {
uint8_t opaque[GOLDI_PUBLIC_KEY_BYTES]; /**< Serialized data. */
};
/**
* @brief Serialized form of a Goldilocks private key.
*
* Contains 56 bytes of actual private key, 56 bytes of
* public key, and 32 bytes of symmetric key for randomization.
*
* @warning This isn't even my final form!
*/
struct goldilocks_private_key_t {
uint8_t opaque[GOLDI_PRIVATE_KEY_BYTES]; /**< Serialized data. */
};
#ifdef __cplusplus
extern "C" {
#endif
/** @brief No error. */
static const int GOLDI_EOK = 0;
/** @brief Error: your key or other state is corrupt. */
static const int GOLDI_ECORRUPT = 44801;
/** @brief Error: other party's key is corrupt. */
static const int GOLDI_EINVAL = 44802;
/** @brief Error: not enough entropy. */
static const int GOLDI_ENODICE = 44804;
/** @brief Error: you need to initialize the library first. */
static const int GOLDI_EUNINIT = 44805;
/** @brief Error: called init() but we are already initialized. */
static const int GOLDI_EALREADYINIT = 44805;
/**
* @brief Initialize Goldilocks' precomputed tables and
* random number generator. This function must be called before
* any of the other Goldilocks routines (except
* goldilocks_shared_secret in the current version) and should be
* called only once per process.
*
* There is currently no way to tear down this state. It is possible
* that a future version of this library will not require this function.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_EALREADYINIT Already initialized.
* @retval GOLDI_ECORRUPT Memory is corrupted, or another thread is already init'ing.
* @retval Nonzero An error occurred.
*/
int
goldilocks_init (void)
__attribute__((warn_unused_result,visibility ("default")));
/**
* @brief Generate a new random keypair.
* @param [out] privkey The generated private key.
* @param [out] pubkey The generated public key.
*
* @warning This isn't even my final form!
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_ENODICE Insufficient entropy.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_keygen (
struct goldilocks_private_key_t *privkey,
struct goldilocks_public_key_t *pubkey
) __attribute__((warn_unused_result,nonnull(1,2),visibility ("default")));
/**
* @brief Derive a key from its compressed form.
* @param [out] privkey The derived private key.
* @param [in] proto The compressed or proto-key, which must be 32 random bytes.
*
* @warning This isn't even my final form!
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_derive_private_key (
struct goldilocks_private_key_t *privkey,
const unsigned char proto[GOLDI_SYMKEY_BYTES]
) __attribute__((nonnull(1,2),visibility ("default")));
/**
* @brief Compress a private key (by copying out the proto-key)
* @param [out] proto The proto-key.
* @param [in] privkey The private key.
*
* @warning This isn't even my final form!
* @todo test.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
void
goldilocks_underive_private_key (
unsigned char proto[GOLDI_SYMKEY_BYTES],
const struct goldilocks_private_key_t *privkey
) __attribute__((nonnull(1,2),visibility ("default")));
/**
* @brief Extract the public key from a private key.
*
* This is essentially a memcpy from the public part of the privkey.
*
* @param [out] pubkey The extracted private key.
* @param [in] privkey The private key.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_ECORRUPT The private key is corrupt.
*/
int
goldilocks_private_to_public (
struct goldilocks_public_key_t *pubkey,
const struct goldilocks_private_key_t *privkey
) __attribute__((nonnull(1,2),visibility ("default")));
/**
* @brief Generate a Diffie-Hellman shared secret in constant time.
*
* This function uses some compile-time flags whose merit remains to
* be decided.
*
* If the flag EXPERIMENT_ECDH_OBLITERATE_CT is set, prepend 40 bytes
* of zeros to the secret before hashing. In the case that the other
* party's key is detectably corrupt, instead the symmetric part
* of the secret key is used to produce a pseudorandom value.
*
* If EXPERIMENT_ECDH_STIR_IN_PUBKEYS is set, the sum and product of
* the two parties' public keys is prepended to the hash.
*
* In the current version, this function can safely be run even without
* goldilocks_init(). But this property is not guaranteed for future
* versions, so call it anyway.
*
* @warning This isn't even my final form!
*
* @param [out] shared The shared secret established with the other party.
* @param [in] my_privkey My private key.
* @param [in] your_pubkey The other party's public key.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_ECORRUPT My key is corrupt.
* @retval GOLDI_EINVAL The other party's key is corrupt.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_shared_secret (
uint8_t shared[GOLDI_SHARED_SECRET_BYTES],
const struct goldilocks_private_key_t *my_privkey,
const struct goldilocks_public_key_t *your_pubkey
) __attribute__((warn_unused_result,nonnull(1,2,3),visibility ("default")));
#if GOLDI_IMPLEMENT_SIGNATURES
/**
* @brief Sign a message.
*
* The signature is deterministic, using the symmetric secret found in the
* secret key to form a nonce.
*
* The technique used in signing is a modified Schnorr system, like EdDSA.
*
* @warning This isn't even my final form!
*
* @param [out] signature_out Space for the output signature.
* @param [in] message The message to be signed.
* @param [in] message_len The length of the message to be signed.
* @param [in] privkey My private key.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_ECORRUPT My key is corrupt.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_sign (
uint8_t signature_out[GOLDI_SIGNATURE_BYTES],
const uint8_t *message,
uint64_t message_len,
const struct goldilocks_private_key_t *privkey
) __attribute__((nonnull(1,2,4),visibility ("default")));
/**
* @brief Verify a signature.
*
* This function is fairly strict. It will correctly detect when
* the signature has the wrong cofactor component, or when the sig
* values aren't less than p or q.
*
* Currently this function does not detect when the public key is weird,
* eg 0, has cofactor, etc. As a result, a party with a bogus public
* key could create signatures that succeed on some systems and fail on
* others.
*
* @warning This isn't even my final form!
*
* @param [in] signature The signature.
* @param [in] message The message to be verified.
* @param [in] message_len The length of the message to be verified.
* @param [in] pubkey The signer's public key.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_EINVAL The public key or signature is corrupt.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_verify (
const uint8_t signature[GOLDI_SIGNATURE_BYTES],
const uint8_t *message,
uint64_t message_len,
const struct goldilocks_public_key_t *pubkey
) __attribute__((warn_unused_result,nonnull(1,2,4),visibility ("default")));
#endif
#if GOLDI_IMPLEMENT_PRECOMPUTED_KEYS
/** A public key which has been expanded by precomputation for higher speed. */
struct goldilocks_precomputed_public_key_t;
/**
* @brief Expand a public key by precomputation.
*
* @todo Give actual error returns, instead of ambiguous NULL.
*
* @warning This isn't even my final form!
*
* @param [in] pub The public key.
* @retval NULL We ran out of memory, or the
*/
struct goldilocks_precomputed_public_key_t *
goldilocks_precompute_public_key (
const struct goldilocks_public_key_t *pub
) __attribute__((warn_unused_result,nonnull(1),visibility ("default")));
/**
* @brief Overwrite an expanded public key with zeros, then destroy it.
*
* If the input is NULL, this function does nothing.
*
* @param [in] precom The public key.
*/
void
goldilocks_destroy_precomputed_public_key (
struct goldilocks_precomputed_public_key_t *precom
) __attribute__((visibility ("default")));
/**
* @brief Verify a signature.
*
* This function is fairly strict. It will correctly detect when
* the signature has the wrong cofactor component, or when the sig
* values aren't less than p or q.
*
* @warning This isn't even my final form!
*
* @param [in] signature The signature.
* @param [in] message The message to be verified.
* @param [in] message_len The length of the message to be verified.
* @param [in] pubkey The signer's public key, expanded by precomputation.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_EINVAL The public key or signature is corrupt.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_verify_precomputed (
const uint8_t signature[GOLDI_SIGNATURE_BYTES],
const uint8_t *message,
uint64_t message_len,
const struct goldilocks_precomputed_public_key_t *pubkey
) __attribute__((warn_unused_result,nonnull(1,2,4),visibility ("default")));
/**
* @brief Generate a Diffie-Hellman shared secret in constant time.
* Uses a precomputation on the other party's public key for efficiency.
*
* This function uses some compile-time flags whose merit remains to
* be decided.
*
* If the flag EXPERIMENT_ECDH_OBLITERATE_CT is set, prepend 40 bytes
* of zeros to the secret before hashing. In the case that the other
* party's key is detectably corrupt, instead the symmetric part
* of the secret key is used to produce a pseudorandom value.
*
* If EXPERIMENT_ECDH_STIR_IN_PUBKEYS is set, the sum and product of
* the two parties' public keys is prepended to the hash.
*
* In the current version, this function can safely be run even without
* goldilocks_init(). But this property is not guaranteed for future
* versions, so call it anyway.
*
* @warning This isn't even my final form!
*
* @param [out] shared The shared secret established with the other party.
* @param [in] my_privkey My private key.
* @param [in] your_pubkey The other party's precomputed public key.
*
* @retval GOLDI_EOK Success.
* @retval GOLDI_ECORRUPT My key is corrupt.
* @retval GOLDI_EINVAL The other party's key is corrupt.
* @retval GOLDI_EUNINIT You must call goldilocks_init() first.
*/
int
goldilocks_shared_secret_precomputed (
uint8_t shared[GOLDI_SHARED_SECRET_BYTES],
const struct goldilocks_private_key_t *my_privkey,
const struct goldilocks_precomputed_public_key_t *your_pubkey
) __attribute__((warn_unused_result,nonnull(1,2,3),visibility ("default")));
#endif /* GOLDI_IMPLEMENT_PRECOMPUTED_KEYS */
#ifdef __cplusplus
}; /* extern "C" */
#endif
#endif /* __GOLDILOCKS_H__ */
......@@ -12,7 +12,8 @@
#include "ec_point.h"
#include "magic.h"
#define is32 (GOLDI_BITS == 32)
#define is32 (GOLDI_BITS == 32 || FIELD_BITS == 480)
/* TODO XXX PERF FIXME: better detection of overflow conditions */
/* I wanted to just use if (is32)
* But clang's -Wunreachable-code flags it.
......@@ -52,60 +53,6 @@ field_mulw_scc_wr (
field_weak_reduce(out);
}
static __inline__ void
field_sqrn (
field_t *__restrict__ y,
const field_t *x,
int n
) {
field_t tmp;
assert(n>0);
if (n&1) {
field_sqr(y,x);
n--;
} else {
field_sqr(&tmp,x);
field_sqr(y,&tmp);
n-=2;
}
for (; n; n-=2) {
field_sqr(&tmp,y);
field_sqr(y,&tmp);
}
}
void
field_isr ( /* TODO: MAGIC */
struct field_t* a,
const struct field_t* x
) {
struct field_t L0, L1, L2;
field_sqr ( &L1, x );
field_mul ( &L2, x, &L1 );
field_sqr ( &L1, &L2 );
field_mul ( &L2, x, &L1 );
field_sqrn ( &L1, &L2, 3 );
field_mul ( &L0, &L2, &L1 );
field_sqrn ( &L1, &L0, 3 );
field_mul ( &L0, &L2, &L1 );
field_sqrn ( &L2, &L0, 9 );
field_mul ( &L1, &L0, &L2 );
field_sqr ( &L0, &L1 );
field_mul ( &L2, x, &L0 );
field_sqrn ( &L0, &L2, 18 );
field_mul ( &L2, &L1, &L0 );
field_sqrn ( &L0, &L2, 37 );
field_mul ( &L1, &L2, &L0 );
field_sqrn ( &L0, &L1, 37 );
field_mul ( &L1, &L2, &L0 );
field_sqrn ( &L0, &L1, 111 );
field_mul ( &L2, &L1, &L0 );
field_sqr ( &L0, &L2 );
field_mul ( &L1, x, &L0 );
field_sqrn ( &L0, &L1, 223 );
field_mul ( a, &L2, &L0 );
}
void
add_tw_niels_to_tw_extensible (
struct tw_extensible_t* d,
......@@ -396,7 +343,7 @@ montgomery_step (
field_sqr ( &a->za, &a->zd );
field_sqr ( &a->xd, &L0 );
field_sqr ( &L0, &L1 );
field_mulw ( &a->zd, &a->xd, 1-EDWARDS_D );
field_mulw_scc ( &a->zd, &a->xd, 1-EDWARDS_D ); /* FIXME PERF MULW */
field_sub ( &L1, &a->xd, &L0 );
field_bias ( &L1, 2 );
IF32( field_weak_reduce( &L1 ) );
......@@ -444,11 +391,9 @@ serialize_montgomery (
field_mul ( &L3, &L1, &L2 );
field_copy ( &L2, &a->z0 );
field_addw ( &L2, 1 );
field_sqr ( &L1, &L2 );
field_mulw ( &L2, &L1, 1-EDWARDS_D );
field_neg ( &L1, &L2 );
field_sqr ( &L0, &L2 );
field_mulw_scc_wr ( &L1, &L0, EDWARDS_D-1 );
field_add ( &L2, &a->z0, &a->z0 );
field_bias ( &L2, 1 );
field_add ( &L0, &L2, &L2 );
field_add ( &L2, &L0, &L1 );
IF32( field_weak_reduce( &L2 ) );
......@@ -512,13 +457,9 @@ untwist_and_double_and_serialize (
IF32( field_weak_reduce( b ) );
field_sqr ( &L2, &a->z );
field_sqr ( &L1, &L2 );
field_add ( &L2, b, b );
field_mulw ( b, &L2, 1-EDWARDS_D );
field_neg ( &L2, b );
field_bias ( &L2, 2 );
field_mulw ( &L0, &L2, 1-EDWARDS_D );
field_neg ( b, &L0 );
field_bias ( b, 2 );
field_add ( b, b, b );
field_mulw_scc ( &L2, b, EDWARDS_D-1 );
field_mulw_scc ( b, &L2, EDWARDS_D-1 );
field_mul ( &L0, &L2, &L1 );
field_mul ( &L2, b, &L0 );
field_isr ( &L0, &L2 );
......@@ -654,10 +595,8 @@ deserialize_affine (
field_copy ( &L3, &L1 );
field_addw ( &L3, 1 );
field_sqr ( &L2, &L3 );
field_mulw ( &L3, &L2, 1-EDWARDS_D );
field_neg ( &a->x, &L3 );
field_add ( &L3, &L1, &L1 );
field_bias ( &L3, 1 );
field_mulw_scc ( &a->x, &L2, EDWARDS_D-1 ); /* PERF MULW */
field_add ( &L3, &L1, &L1 ); /* FIXME: i adjusted the bias here, was it right? */
field_add ( &a->y, &L3, &L3 );
field_add ( &L3, &a->y, &a->x );
IF32( field_weak_reduce( &L3 ) );
......@@ -694,11 +633,9 @@ deserialize_and_twist_approx (
field_sqr ( &a->z, sz );
field_copy ( &a->y, &a->z );
field_addw ( &a->y, 1 );
field_sqr ( &a->x, &a->y );
field_mulw ( &a->y, &a->x, 1-EDWARDS_D );
field_neg ( &a->x, &a->y );
field_sqr ( &L0, &a->y );
field_mulw_scc ( &a->x, &L0, EDWARDS_D-1 );
field_add ( &a->y, &a->z, &a->z );
field_bias ( &a->y, 1 );
field_add ( &a->u, &a->y, &a->y );
field_add ( &a->y, &a->u, &a->x );
IF32( field_weak_reduce( &a->y ) );
......
......@@ -543,8 +543,6 @@ copy_tw_pniels (
field_copy ( &a->z, &ds->z );
}