Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • briansmith/nettle
  • justus/nettle
  • nettle/nettle
  • michaelweiser/nettle
  • aberaud/nettle
  • npocs/nettle
  • ajlawrence/nettle
  • mhoffmann/nettle
  • lumag/nettle
  • mamonet/nettle
  • devnexen/nettle
  • babelouest/nettle
  • ueno/nettle
  • rth/nettle
  • wiml/nettle
15 results
Select Git revision
Show changes
/* dsa-sign.c
The DSA publickey algorithm.
Copyright (C) 2002, 2010 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include "dsa.h"
#include "dsa-internal.h"
#include "bignum.h"
#include "gmp-glue.h"
int
dsa_sign(const struct dsa_params *params,
const mpz_t x,
void *random_ctx, nettle_random_func *random,
size_t digest_size,
const uint8_t *digest,
struct dsa_signature *signature)
{
mpz_t k;
mpz_t h;
mpz_t tmp;
unsigned bit_size;
unsigned limb_size;
int res;
/* Check that p is odd, so that invalid keys don't result in a crash
inside mpz_powm_sec. */
if (mpz_even_p (params->p))
return 0;
/* Select k, 0<k<q, randomly */
mpz_init_set(tmp, params->q);
mpz_sub_ui(tmp, tmp, 1);
mpz_init(k);
nettle_mpz_random(k, random_ctx, random, tmp);
mpz_add_ui(k, k, 1);
/* Compute r = (g^k (mod p)) (mod q) */
mpz_powm_sec(tmp, params->g, k, params->p);
mpz_fdiv_r(signature->r, tmp, params->q);
/* Compute hash */
bit_size = mpz_sizeinbase(params->q, 2);
limb_size = NETTLE_BIT_SIZE_TO_LIMB_SIZE(bit_size);
mpz_init(h);
_nettle_dsa_hash (mpz_limbs_write (h, limb_size), bit_size, digest_size, digest);
mpz_limbs_finish (h, limb_size);
/* Compute k^-1 (mod q) */
if (mpz_invert(k, k, params->q))
{
/* Compute signature s = k^-1 (h + xr) (mod q) */
mpz_mul(tmp, signature->r, x);
mpz_fdiv_r(tmp, tmp, params->q);
mpz_add(tmp, tmp, h);
mpz_mul(tmp, tmp, k);
mpz_fdiv_r(signature->s, tmp, params->q);
res = 1;
}
else
/* What do we do now? The key is invalid. */
res = 0;
mpz_clear(k);
mpz_clear(h);
mpz_clear(tmp);
return res;
}
/* dsa-verify.c
The DSA publickey algorithm.
Copyright (C) 2002, 2003 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "dsa.h"
#include "dsa-internal.h"
#include "gmp-glue.h"
int
dsa_verify(const struct dsa_params *params,
const mpz_t y,
size_t digest_size,
const uint8_t *digest,
const struct dsa_signature *signature)
{
mpz_t w;
mpz_t tmp;
mpz_t v;
unsigned bit_size;
unsigned limb_size;
int res;
/* Check that r and s are in the proper range */
if (mpz_sgn(signature->r) <= 0 || mpz_cmp(signature->r, params->q) >= 0)
return 0;
if (mpz_sgn(signature->s) <= 0 || mpz_cmp(signature->s, params->q) >= 0)
return 0;
mpz_init(w);
/* Compute w = s^-1 (mod q) */
/* NOTE: In gmp-2, mpz_invert sometimes generates negative inverses,
* so we need gmp-3 or better. */
if (!mpz_invert(w, signature->s, params->q))
{
mpz_clear(w);
return 0;
}
mpz_init(tmp);
mpz_init(v);
/* The message digest */
bit_size = mpz_sizeinbase(params->q, 2);
limb_size = NETTLE_BIT_SIZE_TO_LIMB_SIZE(bit_size);
_nettle_dsa_hash (mpz_limbs_write (tmp, limb_size), bit_size, digest_size, digest);
mpz_limbs_finish (tmp, limb_size);
/* v = g^{w * h (mod q)} (mod p) */
mpz_mul(tmp, tmp, w);
mpz_fdiv_r(tmp, tmp, params->q);
mpz_powm(v, params->g, tmp, params->p);
/* y^{w * r (mod q) } (mod p) */
mpz_mul(tmp, signature->r, w);
mpz_fdiv_r(tmp, tmp, params->q);
mpz_powm(tmp, y, tmp, params->p);
/* v = (g^{w * h} * y^{w * r} (mod p) ) (mod q) */
mpz_mul(v, v, tmp);
mpz_fdiv_r(v, v, params->p);
mpz_fdiv_r(v, v, params->q);
res = !mpz_cmp(v, signature->r);
mpz_clear(w);
mpz_clear(tmp);
mpz_clear(v);
return res;
}
/* dsa.c
The DSA publickey algorithm.
Copyright (C) 2002 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "dsa.h"
#include "dsa-internal.h"
#include "bignum.h"
void
dsa_params_init (struct dsa_params *params)
{
mpz_init(params->p);
mpz_init(params->q);
mpz_init(params->g);
}
void
dsa_params_clear (struct dsa_params *params)
{
mpz_clear(params->p);
mpz_clear(params->q);
mpz_clear(params->g);
}
void
dsa_signature_init(struct dsa_signature *signature)
{
mpz_init(signature->r);
mpz_init(signature->s);
}
void
dsa_signature_clear(struct dsa_signature *signature)
{
mpz_clear(signature->r);
mpz_clear(signature->s);
}
/* dsa.h
The DSA publickey algorithm.
Copyright (C) 2002, 2013, 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#ifndef NETTLE_DSA_H_INCLUDED
#define NETTLE_DSA_H_INCLUDED
#include "nettle-types.h"
#include "bignum.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Name mangling */
#define dsa_params_init nettle_dsa_params_init
#define dsa_params_clear nettle_dsa_params_clear
#define dsa_signature_init nettle_dsa_signature_init
#define dsa_signature_clear nettle_dsa_signature_clear
#define dsa_sign nettle_dsa_sign
#define dsa_verify nettle_dsa_verify
#define dsa_generate_params nettle_dsa_generate_params
#define dsa_generate_keypair nettle_dsa_generate_keypair
#define dsa_signature_from_sexp nettle_dsa_signature_from_sexp
#define dsa_keypair_to_sexp nettle_dsa_keypair_to_sexp
#define dsa_keypair_from_sexp_alist nettle_dsa_keypair_from_sexp_alist
#define dsa_sha1_keypair_from_sexp nettle_dsa_sha1_keypair_from_sexp
#define dsa_sha256_keypair_from_sexp nettle_dsa_sha256_keypair_from_sexp
#define dsa_params_from_der_iterator nettle_dsa_params_from_der_iterator
#define dsa_public_key_from_der_iterator nettle_dsa_public_key_from_der_iterator
#define dsa_openssl_private_key_from_der_iterator nettle_dsa_openssl_private_key_from_der_iterator
#define dsa_openssl_private_key_from_der nettle_openssl_provate_key_from_der
/* For FIPS approved parameters */
#define DSA_SHA1_MIN_P_BITS 512
#define DSA_SHA1_Q_OCTETS 20
#define DSA_SHA1_Q_BITS 160
#define DSA_SHA256_MIN_P_BITS 1024
#define DSA_SHA256_Q_OCTETS 32
#define DSA_SHA256_Q_BITS 256
struct dsa_params
{
/* Modulo */
mpz_t p;
/* Group order */
mpz_t q;
/* Generator */
mpz_t g;
};
void
dsa_params_init (struct dsa_params *params);
void
dsa_params_clear (struct dsa_params *params);
struct dsa_signature
{
mpz_t r;
mpz_t s;
};
/* Calls mpz_init to initialize bignum storage. */
void
dsa_signature_init(struct dsa_signature *signature);
/* Calls mpz_clear to deallocate bignum storage. */
void
dsa_signature_clear(struct dsa_signature *signature);
int
dsa_sign(const struct dsa_params *params,
const mpz_t x,
void *random_ctx, nettle_random_func *random,
size_t digest_size,
const uint8_t *digest,
struct dsa_signature *signature);
int
dsa_verify(const struct dsa_params *params,
const mpz_t y,
size_t digest_size,
const uint8_t *digest,
const struct dsa_signature *signature);
/* Key generation */
int
dsa_generate_params(struct dsa_params *params,
void *random_ctx, nettle_random_func *random,
void *progress_ctx, nettle_progress_func *progress,
unsigned p_bits, unsigned q_bits);
void
dsa_generate_keypair (const struct dsa_params *params,
mpz_t pub, mpz_t key,
void *random_ctx, nettle_random_func *random);
/* Keys in sexp form. */
struct nettle_buffer;
/* Generates a public-key expression if PRIV is NULL .*/
int
dsa_keypair_to_sexp(struct nettle_buffer *buffer,
const char *algorithm_name, /* NULL means "dsa" */
const struct dsa_params *params,
const mpz_t pub,
const mpz_t priv);
struct sexp_iterator;
int
dsa_signature_from_sexp(struct dsa_signature *rs,
struct sexp_iterator *i,
unsigned q_bits);
int
dsa_keypair_from_sexp_alist(struct dsa_params *params,
mpz_t pub,
mpz_t priv,
unsigned p_max_bits,
unsigned q_bits,
struct sexp_iterator *i);
/* If PRIV is NULL, expect a public-key expression. If PUB is NULL,
* expect a private key expression and ignore the parts not needed for
* the public key. */
/* Keys must be initialized before calling this function, as usual. */
int
dsa_sha1_keypair_from_sexp(struct dsa_params *params,
mpz_t pub,
mpz_t priv,
unsigned p_max_bits,
size_t length, const uint8_t *expr);
int
dsa_sha256_keypair_from_sexp(struct dsa_params *params,
mpz_t pub,
mpz_t priv,
unsigned p_max_bits,
size_t length, const uint8_t *expr);
/* Keys in X.509 andd OpenSSL format. */
struct asn1_der_iterator;
int
dsa_params_from_der_iterator(struct dsa_params *params,
unsigned max_bits, unsigned q_bits,
struct asn1_der_iterator *i);
int
dsa_public_key_from_der_iterator(const struct dsa_params *params,
mpz_t pub,
struct asn1_der_iterator *i);
int
dsa_openssl_private_key_from_der_iterator(struct dsa_params *params,
mpz_t pub,
mpz_t priv,
unsigned p_max_bits,
struct asn1_der_iterator *i);
int
dsa_openssl_private_key_from_der(struct dsa_params *params,
mpz_t pub,
mpz_t priv,
unsigned p_max_bits,
size_t length, const uint8_t *data);
#ifdef __cplusplus
}
#endif
#endif /* NETTLE_DSA_H_INCLUDED */
/* dsa2sexp.c
Copyright (C) 2002, 2009, 2014 Niels Möller, Magnus Holmgren
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "dsa.h"
#include "sexp.h"
int
dsa_keypair_to_sexp(struct nettle_buffer *buffer,
const char *algorithm_name,
const struct dsa_params *params,
const mpz_t pub,
const mpz_t priv)
{
if (!algorithm_name)
algorithm_name = "dsa";
if (priv)
return sexp_format(buffer,
"(private-key(%0s(p%b)(q%b)"
"(g%b)(y%b)(x%b)))",
algorithm_name, params->p, params->q,
params->g, pub, priv);
else
return sexp_format(buffer,
"(public-key(%0s(p%b)(q%b)"
"(g%b)(y%b)))",
algorithm_name, params->p, params->q,
params->g, pub);
}
/* eax-aes128-meta.c
Copyright (C) 2013, 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "eax.h"
#include "nettle-meta.h"
static nettle_set_key_func eax_aes128_set_nonce_wrapper;
static void
eax_aes128_set_nonce_wrapper (void *ctx, const uint8_t *nonce)
{
eax_aes128_set_nonce (ctx, EAX_IV_SIZE, nonce);
}
const struct nettle_aead
nettle_eax_aes128 =
{ "eax_aes128", sizeof(struct eax_aes128_ctx),
EAX_BLOCK_SIZE, AES128_KEY_SIZE,
EAX_IV_SIZE, EAX_DIGEST_SIZE,
(nettle_set_key_func *) eax_aes128_set_key,
(nettle_set_key_func *) eax_aes128_set_key,
eax_aes128_set_nonce_wrapper,
(nettle_hash_update_func *) eax_aes128_update,
(nettle_crypt_func *) eax_aes128_encrypt,
(nettle_crypt_func *) eax_aes128_decrypt,
(nettle_hash_digest_func *) eax_aes128_digest
};
/* eax-aes128.c
Copyright (C) 2013, 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "eax.h"
void
eax_aes128_set_key(struct eax_aes128_ctx *ctx, const uint8_t *key)
{
EAX_SET_KEY(ctx,
aes128_set_encrypt_key, aes128_encrypt,
key);
}
void
eax_aes128_set_nonce(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *iv)
{
EAX_SET_NONCE(ctx, aes128_encrypt, length, iv);
}
void
eax_aes128_update(struct eax_aes128_ctx *ctx, size_t length, const uint8_t *data)
{
EAX_UPDATE(ctx, aes128_encrypt, length, data);
}
void
eax_aes128_encrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src)
{
EAX_ENCRYPT(ctx, aes128_encrypt, length, dst, src);
}
void
eax_aes128_decrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src)
{
EAX_DECRYPT(ctx, aes128_encrypt, length, dst, src);
}
void
eax_aes128_digest(struct eax_aes128_ctx *ctx,
uint8_t *digest)
{
EAX_DIGEST(ctx, aes128_encrypt, digest);
}
/* eax.c
EAX mode, see http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
Copyright (C) 2013 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <string.h>
#include "eax.h"
#include "block-internal.h"
#include "ctr.h"
#include "memxor.h"
static void
omac_init (union nettle_block16 *state, unsigned t)
{
memset (state->b, 0, EAX_BLOCK_SIZE - 1);
state->b[EAX_BLOCK_SIZE - 1] = t;
}
static void
omac_update (union nettle_block16 *state, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t length, const uint8_t *data)
{
for (; length >= EAX_BLOCK_SIZE;
length -= EAX_BLOCK_SIZE, data += EAX_BLOCK_SIZE)
{
f (cipher, EAX_BLOCK_SIZE, state->b, state->b);
memxor (state->b, data, EAX_BLOCK_SIZE);
}
if (length > 0)
{
/* Allowed only for the last call */
f (cipher, EAX_BLOCK_SIZE, state->b, state->b);
memxor (state->b, data, length);
state->b[length] ^= 0x80;
/* XOR with (P ^ B), since the digest processing
* unconditionally XORs with B */
block16_xor (state, &key->pad_partial);
}
}
static void
omac_final (union nettle_block16 *state, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f)
{
block16_xor (state, &key->pad_block);
f (cipher, EAX_BLOCK_SIZE, state->b, state->b);
}
void
eax_set_key (struct eax_key *key, const void *cipher, nettle_cipher_func *f)
{
static const union nettle_block16 zero_block;
f (cipher, EAX_BLOCK_SIZE, key->pad_block.b, zero_block.b);
block16_mulx_be (&key->pad_block, &key->pad_block);
block16_mulx_be (&key->pad_partial, &key->pad_block);
block16_xor (&key->pad_partial, &key->pad_block);
}
void
eax_set_nonce (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t nonce_length, const uint8_t *nonce)
{
omac_init (&eax->omac_nonce, 0);
omac_update (&eax->omac_nonce, key, cipher, f, nonce_length, nonce);
omac_final (&eax->omac_nonce, key, cipher, f);
memcpy (eax->ctr.b, eax->omac_nonce.b, EAX_BLOCK_SIZE);
omac_init (&eax->omac_data, 1);
omac_init (&eax->omac_message, 2);
}
void
eax_update (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t data_length, const uint8_t *data)
{
omac_update (&eax->omac_data, key, cipher, f, data_length, data);
}
void
eax_encrypt (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t length, uint8_t *dst, const uint8_t *src)
{
ctr_crypt (cipher, f, EAX_BLOCK_SIZE, eax->ctr.b, length, dst, src);
omac_update (&eax->omac_message, key, cipher, f, length, dst);
}
void
eax_decrypt (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t length, uint8_t *dst, const uint8_t *src)
{
omac_update (&eax->omac_message, key, cipher, f, length, src);
ctr_crypt (cipher, f, EAX_BLOCK_SIZE, eax->ctr.b, length, dst, src);
}
void
eax_digest (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
uint8_t *digest)
{
omac_final (&eax->omac_data, key, cipher, f);
omac_final (&eax->omac_message, key, cipher, f);
block16_xor (&eax->omac_nonce, &eax->omac_data);
memxor3 (digest, eax->omac_nonce.b, eax->omac_message.b, EAX_DIGEST_SIZE);
}
/* eax.h
EAX mode, see http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
Copyright (C) 2013 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#ifndef NETTLE_EAX_H_INCLUDED
#define NETTLE_EAX_H_INCLUDED
#include "aes.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Name mangling */
#define eax_set_key nettle_eax_set_key
#define eax_set_nonce nettle_eax_set_nonce
#define eax_update nettle_eax_update
#define eax_encrypt nettle_eax_encrypt
#define eax_decrypt nettle_eax_decrypt
#define eax_digest nettle_eax_digest
#define eax_aes128_set_key nettle_eax_aes128_set_key
#define eax_aes128_set_nonce nettle_eax_aes128_set_nonce
#define eax_aes128_update nettle_eax_aes128_update
#define eax_aes128_encrypt nettle_eax_aes128_encrypt
#define eax_aes128_decrypt nettle_eax_aes128_decrypt
#define eax_aes128_digest nettle_eax_aes128_digest
/* Restricted to block ciphers with 128 bit block size. FIXME: Reflect
this in naming? */
#define EAX_BLOCK_SIZE 16
#define EAX_DIGEST_SIZE 16
/* FIXME: Reasonable default? */
#define EAX_IV_SIZE 16
/* Values independent of message and nonce */
struct eax_key
{
union nettle_block16 pad_block;
union nettle_block16 pad_partial;
};
struct eax_ctx
{
union nettle_block16 omac_nonce;
union nettle_block16 omac_data;
union nettle_block16 omac_message;
union nettle_block16 ctr;
};
void
eax_set_key (struct eax_key *key, const void *cipher, nettle_cipher_func *f);
void
eax_set_nonce (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t nonce_length, const uint8_t *nonce);
void
eax_update (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t data_length, const uint8_t *data);
void
eax_encrypt (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_decrypt (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_digest (struct eax_ctx *eax, const struct eax_key *key,
const void *cipher, nettle_cipher_func *f,
uint8_t *digest);
/* Put the cipher last, to get cipher-independent offsets for the EAX
* state. */
#define EAX_CTX(type) \
{ struct eax_key key; struct eax_ctx eax; type cipher; }
#define EAX_SET_KEY(ctx, set_key, encrypt, data) \
do { \
(set_key)(&(ctx)->cipher, (data)); \
if (0) (encrypt) (&(ctx)->cipher, ~(size_t) 0, \
(uint8_t *) 0, (const uint8_t *) 0); \
eax_set_key (&(ctx)->key, &(ctx)->cipher, (nettle_cipher_func *) encrypt); \
} while (0)
#define EAX_SET_NONCE(ctx, encrypt, length, nonce) \
(0 ? (encrypt) (&(ctx)->cipher, ~(size_t) 0, \
(uint8_t *) 0, (const uint8_t *) 0) \
: eax_set_nonce (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_cipher_func *) (encrypt), \
(length), (nonce)))
#define EAX_UPDATE(ctx, encrypt, length, data) \
(0 ? (encrypt) (&(ctx)->cipher, ~(size_t) 0, \
(uint8_t *) 0, (const uint8_t *) 0) \
: eax_update (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_cipher_func *) (encrypt), \
(length), (data)))
#define EAX_ENCRYPT(ctx, encrypt, length, dst, src) \
(0 ? (encrypt) (&(ctx)->cipher, ~(size_t) 0, \
(uint8_t *) 0, (const uint8_t *) 0) \
: eax_encrypt (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_cipher_func *) (encrypt), \
(length), (dst), (src)))
#define EAX_DECRYPT(ctx, encrypt, length, dst, src) \
(0 ? (encrypt) (&(ctx)->cipher, ~(size_t) 0, \
(uint8_t *) 0, (const uint8_t *) 0) \
: eax_decrypt (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_cipher_func *) (encrypt), \
(length), (dst), (src)))
#define EAX_DIGEST(ctx, encrypt, digest) \
(0 ? (encrypt) (&(ctx)->cipher, ~(size_t) 0, \
(uint8_t *) 0, (const uint8_t *) 0) \
: eax_digest (&(ctx)->eax, &(ctx)->key, \
&(ctx)->cipher, (nettle_cipher_func *) (encrypt), \
(digest)))
struct eax_aes128_ctx EAX_CTX(struct aes128_ctx);
void
eax_aes128_set_key(struct eax_aes128_ctx *ctx, const uint8_t *key);
void
eax_aes128_set_nonce(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *iv);
void
eax_aes128_update(struct eax_aes128_ctx *ctx,
size_t length, const uint8_t *data);
void
eax_aes128_encrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_aes128_decrypt(struct eax_aes128_ctx *ctx,
size_t length, uint8_t *dst, const uint8_t *src);
void
eax_aes128_digest(struct eax_aes128_ctx *ctx, uint8_t *digest);
#ifdef __cplusplus
}
#endif
#endif /* NETTLE_EAX_H_INCLUDED */
/* ecc-a-to-j.c
Copyright (C) 2013 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
/* Development of Nettle's ECC support was funded by the .SE Internet Fund. */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
void
ecc_a_to_j (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p)
{
if (ecc->use_redc)
{
mpn_copyd (r + ecc->p.size, p, 2*ecc->p.size);
mpn_zero (r, ecc->p.size);
ecc->p.mod (&ecc->p, r, r);
mpn_zero (r + ecc->p.size, ecc->p.size);
ecc->p.mod (&ecc->p, r + ecc->p.size, r + ecc->p.size);
}
else if (r != p)
mpn_copyi (r, p, 2*ecc->p.size);
mpn_copyi (r + 2*ecc->p.size, ecc->unit, ecc->p.size);
}
/* ecc-add-eh.c
Copyright (C) 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
/* Add two points on an Edwards curve, with result and first point in
homogeneous coordinates. */
void
ecc_add_eh (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 q
#define y2 (q + ecc->p.size)
#define x3 r
#define y3 (r + ecc->p.size)
#define z3 (r + 2*ecc->p.size)
/* Formulas (from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-edwards-projective.html#doubling-dbl-2007-bl):
Computation Operation Live variables
C = x1*x2 mul C
D = y1*y2 mul C, D
T = (x1+y1)(x2+y2) - C - D C, D, T
E = b*C*D 2 mul C, E, T (Replace C <-- D - C)
B = z1^2 sqr B, C, E, T
F = B - E B, C, E, F, T
G = B + E C, F, G, T
x3 = z1*F*T 3 mul C, F, G, T
y3 = z1*G*(D-C) 2 mul F, G
z3 = F*G mul
*/
#define T scratch
#define E (scratch + 1*ecc->p.size)
#define G E
#define C (scratch + 2*ecc->p.size)
#define D (scratch + 3*ecc->p.size)
#define B D
/* Use T as scratch, clobber E */
ecc_mod_mul (&ecc->p, C, x1, x2, T); /* C */
ecc_mod_mul (&ecc->p, D, y1, y2, T); /* C, D */
ecc_mod_add (&ecc->p, x3, x1, y1);
ecc_mod_add (&ecc->p, y3, x2, y2);
ecc_mod_mul (&ecc->p, T, x3, y3, T); /* C, D, T */
ecc_mod_sub (&ecc->p, T, T, C);
ecc_mod_sub (&ecc->p, T, T, D);
/* Can now use x3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, T, T, z1, x3);
ecc_mod_mul (&ecc->p, E, C, D, x3); /* C, D, T, E */
ecc_mod_mul (&ecc->p, E, E, ecc->b, x3);
ecc_mod_sub (&ecc->p, C, D, C); /* C, T, E */
ecc_mod_mul (&ecc->p, C, C, z1, x3);
ecc_mod_sqr (&ecc->p, B, z1, x3); /* C, T, E, B */
ecc_mod_sub (&ecc->p, x3, B, E);
ecc_mod_add (&ecc->p, G, B, E); /* C, T, G */
/* Can now use y3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, y3, C, G, y3); /* T G */
/* Can use C--D as scratch */
ecc_mod_mul (&ecc->p, z3, x3, G, C); /* T */
ecc_mod_mul (&ecc->p, x3, x3, T, C);
}
/* ecc-add-ehh.c
Copyright (C) 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
/* Add two points on an Edwards curve, in homogeneous coordinates */
void
ecc_add_ehh (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 q
#define y2 (q + ecc->p.size)
#define z2 (q + 2*ecc->p.size)
#define x3 r
#define y3 (r + ecc->p.size)
#define z3 (r + 2*ecc->p.size)
/* Formulas (from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-edwards-projective.html#addition-add-2007-bl):
Computation Operation Live variables
C = x1*x2 mul C
D = y1*y2 mul C, D
T = (x1+y1)(x2+y2) - C - D, mul C, D, T
E = b*C*D 2 mul C, E, T (Replace C <-- D - C)
A = z1*z2 mul A, C, E, T
B = A^2 sqr A, B, C, E, T
F = B - E A, B, C, E, F, T
G = B + E A, C, F, G, T
x3 = A*F*T 2 mul A, C, G
y3 = A*G*(D-C) 2 mul F, G
z3 = F*G mul
*/
#define T scratch
#define E (scratch + 1*ecc->p.size)
#define G E
#define C (scratch + 2*ecc->p.size)
#define D (scratch + 3*ecc->p.size)
#define B D
/* Use T as scratch, clobber E */
ecc_mod_mul (&ecc->p, C, x1, x2, T); /* C */
ecc_mod_mul (&ecc->p, D, y1, y2, T); /* C, D */
ecc_mod_add (&ecc->p, x3, x1, y1);
ecc_mod_add (&ecc->p, y3, x2, y2);
ecc_mod_mul (&ecc->p, T, x3, y3, T); /* C, D, T */
ecc_mod_sub (&ecc->p, T, T, C);
ecc_mod_sub (&ecc->p, T, T, D);
/* Can now use x3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, E, C, D, x3); /* C, D, T, E */
ecc_mod_mul (&ecc->p, E, E, ecc->b, x3);
ecc_mod_sub (&ecc->p, C, D, C); /* C, T, E */
ecc_mod_mul (&ecc->p, B, z1, z2, x3); /* C, T, E, B */
ecc_mod_mul (&ecc->p, C, C, B, x3);
ecc_mod_mul (&ecc->p, T, T, B, x3);
ecc_mod_sqr (&ecc->p, B, B, x3);
ecc_mod_sub (&ecc->p, x3, B, E);
ecc_mod_add (&ecc->p, G, B, E); /* C, T, G */
/* Can now use y3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, y3, C, G, y3); /* T G */
/* Can use C--D as scratch */
ecc_mod_mul (&ecc->p, z3, x3, G, C); /* T */
ecc_mod_mul (&ecc->p, x3, x3, T, C);
}
/* ecc-add-jj.c
Copyright (C) 2013 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
/* Development of Nettle's ECC support was funded by the .SE Internet Fund. */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
/* NOTE: Behaviour for corner cases:
+ p = 0 ==> r = 0 (invalid except if also q = 0)
+ q = 0 ==> r = invalid
+ p = -q ==> r = 0, correct!
+ p = q ==> r = 0, invalid
*/
void
ecc_add_jja (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 q
#define y2 (q + ecc->p.size)
#define x3 r
#define y3 (r + ecc->p.size)
#define z3 (r + 2*ecc->p.size)
/* Formulas, from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b):
Computation Operation Live variables
ZZ = Z_1^2 sqr ZZ
H = X_2*ZZ - X_1 mul (djb: U_2) ZZ, H
HH = H^2 sqr ZZ, H, HH
ZZZ = ZZ*Z_1 mul ZZ, H, HH, ZZZ
Z_3 = (Z_1+H)^2-ZZ-HH sqr H, HH, ZZZ
W = 2 (Y_2*ZZZ - Y_1) mul (djb: S_2) H, HH, W
I = 4*HH H, W, I
J = H*I mul W, I, J
V = X_1*I mul W, J, V
X_3 = W^2-J-2*V sqr W, J, V
Y_3 = W*(V-X_3)-2*Y_1*J mul, mul
*/
#define zz scratch
#define h (scratch + ecc->p.size)
#define w (scratch + 2*ecc->p.size)
#define hh zz
#define i zz
#define v zz
#define j h
#define tp (scratch + 3*ecc->p.size)
/* zz */
ecc_mod_sqr (&ecc->p, zz, z1, tp); /* zz */
/* h*/
ecc_mod_mul (&ecc->p, h, x2, zz, tp); /* zz, h */
ecc_mod_sub (&ecc->p, h, h, x1);
/* Do z^3 early, store at w. */
ecc_mod_mul (&ecc->p, w, zz, z1, tp); /* zz, h, w */
/* z_3 */
ecc_mod_add (&ecc->p, z3, z1, h);
ecc_mod_sqr (&ecc->p, z3, z3, tp);
ecc_mod_sub (&ecc->p, z3, z3, zz); /* h, w */
/* hh */
ecc_mod_sqr (&ecc->p, hh, h, tp); /* h, w, hh */
ecc_mod_sub (&ecc->p, z3, z3, hh);
/* w */
ecc_mod_mul (&ecc->p, w, y2, w, tp);
ecc_mod_sub (&ecc->p, w, w, y1);
ecc_mod_add (&ecc->p, w, w, w);
/* i replaces hh */
ecc_mod_mul_1 (&ecc->p, i, hh, 4); /* h, w, i */
/* j replaces h */
ecc_mod_mul (&ecc->p, j, i, h, tp); /* w, i, j */
/* v replaces i */
ecc_mod_mul (&ecc->p, v, x1, i, tp);
/* x_3 */
ecc_mod_sqr (&ecc->p, x3, w, tp);
ecc_mod_sub (&ecc->p, x3, x3, j);
ecc_mod_submul_1 (&ecc->p, x3, v, 2);
/* y_3 */
ecc_mod_mul (&ecc->p, j, y1, j, tp);
ecc_mod_sub (&ecc->p, y3, v, x3);
ecc_mod_mul (&ecc->p, y3, y3, w, tp);
ecc_mod_submul_1 (&ecc->p, y3, j, 2);
}
/* ecc-add-jjj.c
Copyright (C) 2013 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
/* Development of Nettle's ECC support was funded by the .SE Internet Fund. */
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
void
ecc_add_jjj (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 q
#define y2 (q + ecc->p.size)
#define z2 (q + 2*ecc->p.size)
#define x3 r
#define y3 (r + ecc->p.size)
#define z3 (r + 2*ecc->p.size)
/* Formulas, from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl:
Computation Operation Live variables
Z1Z1 = Z1^2 sqr Z1Z1
Z2Z2 = Z2^2 sqr Z1Z1, Z2Z2
U1 = X1*Z2Z2 mul Z1Z1, Z2Z2, U1
U2 = X2*Z1Z1 mul Z1Z1, Z2Z2, U1, U2
H = U2-U1 Z1Z1, Z2Z2, U1, H
Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H sqr, mul Z1Z1, Z2Z2, U1, H
S1 = Y1*Z2*Z2Z2 mul, mul Z1Z1, U1, H, S1
S2 = Y2*Z1*Z1Z1 mul, mul U1, H, S1, S2
W = 2*(S2-S1) (djb: r) U1, H, S1, W
I = (2*H)^2 sqr U1, H, S1, W, I
J = H*I mul U1, S1, W, J, V
V = U1*I mul S1, W, J, V
X3 = W^2-J-2*V sqr S1, W, J, V
Y3 = W*(V-X3)-2*S1*J mul, mul
*/
#define h scratch
#define z1z1 (scratch + ecc->p.size)
#define z2z2 z1z1
#define z1z2 (scratch + 2*ecc->p.size)
#define w (scratch + ecc->p.size)
#define i (scratch + 2*ecc->p.size)
#define j h
#define v i
#define tp (scratch + 3*ecc->p.size)
ecc_mod_sqr (&ecc->p, z2z2, z2, tp); /* z2z2 */
/* Store u1 at x3 */
ecc_mod_mul (&ecc->p, x3, x1, z2z2, tp); /* z2z2 */
ecc_mod_add (&ecc->p, z1z2, z1, z2); /* z2z2, z1z2 */
ecc_mod_sqr (&ecc->p, z1z2, z1z2, tp);
ecc_mod_sub (&ecc->p, z1z2, z1z2, z2z2); /* z2z2, z1z2 */
/* Do s1 early, store at y3 */
ecc_mod_mul (&ecc->p, z2z2, z2z2, z2, tp); /* z2z2, z1z2 */
ecc_mod_mul (&ecc->p, y3, z2z2, y1, tp); /* z1z2 */
ecc_mod_sqr (&ecc->p, z1z1, z1, tp); /* z1z1, z1z2 */
ecc_mod_sub (&ecc->p, z1z2, z1z2, z1z1);
ecc_mod_mul (&ecc->p, h, x2, z1z1, tp); /* z1z1, z1z2, h */
ecc_mod_sub (&ecc->p, h, h, x3);
/* z1^3 */
ecc_mod_mul (&ecc->p, z1z1, z1z1, z1, tp);
/* z3 <-- h z1 z2 delayed until now, since that may clobber z1. */
ecc_mod_mul (&ecc->p, z3, z1z2, h, tp); /* z1z1, h */
/* w = 2 (s2 - s1) */
ecc_mod_mul (&ecc->p, w, z1z1, y2, tp); /* h, w */
ecc_mod_sub (&ecc->p, w, w, y3);
ecc_mod_add (&ecc->p, w, w, w);
/* i = (2h)^2 */
ecc_mod_add (&ecc->p, i, h, h); /* h, w, i */
ecc_mod_sqr (&ecc->p, i, i, tp);
/* j and h can overlap */
ecc_mod_mul (&ecc->p, j, h, i, tp); /* j, w, i */
/* v and i can overlap */
ecc_mod_mul (&ecc->p, v, x3, i, tp); /* j, w, v */
/* x3 <-- w^2 - j - 2v */
ecc_mod_sqr (&ecc->p, x3, w, tp);
ecc_mod_sub (&ecc->p, x3, x3, j);
ecc_mod_submul_1 (&ecc->p, x3, v, 2);
/* y3 <-- w (v - x3) - 2 s1 j */
ecc_mod_mul (&ecc->p, j, j, y3, tp);
ecc_mod_sub (&ecc->p, v, v, x3);
ecc_mod_mul (&ecc->p, y3, v, w, tp);
ecc_mod_submul_1 (&ecc->p, y3, j, 2);
}
/* ecc-add-th.c
Copyright (C) 2014, 2017 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
/* Add two points on a twisted Edwards curve, with result and first point in
homogeneous coordinates. */
void
ecc_add_th (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 q
#define y2 (q + ecc->p.size)
#define x3 r
#define y3 (r + ecc->p.size)
#define z3 (r + 2*ecc->p.size)
/* Formulas (from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-madd-2008-bbjlp
Computation Operation Live variables
C = x1*x2 mul C
D = y1*y2 mul C, D
T = (x1+y1)*(x2+y2) mul C, D, T
- C - D
E = b*C*D 2 mul C, E, T (Replace C <-- D+C)
B = z1^2 sqr B, C, E, T
F = B - E B, C, E, F, T
G = B + E C, F, G, T
x3 = z1 * F * T 2 mul C, F, G, T
y3 = z1*G*(D+C) 2 mul F, G
z3 = F*G mul
10M + 1S
We have different sign for E, hence swapping F and G, because our
ecc->b corresponds to -b above.
*/
#define T scratch
#define E (scratch + 1*ecc->p.size)
#define F E
#define C (scratch + 2*ecc->p.size)
#define D (scratch + 3*ecc->p.size)
#define B D
/* Use T as scratch, clobber E */
ecc_mod_mul (&ecc->p, C, x1, x2, T); /* C */
ecc_mod_mul (&ecc->p, D, y1, y2, T); /* C, D */
ecc_mod_add (&ecc->p, x3, x1, y1);
ecc_mod_add (&ecc->p, y3, x2, y2);
ecc_mod_mul (&ecc->p, T, x3, y3, T); /* C, D, T */
ecc_mod_sub (&ecc->p, T, T, C);
ecc_mod_sub (&ecc->p, T, T, D);
/* Can now use x3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, T, T, z1, x3);
ecc_mod_mul (&ecc->p, E, C, D, x3); /* C, D, T, E */
ecc_mod_mul (&ecc->p, E, E, ecc->b, x3);
ecc_mod_add (&ecc->p, C, D, C); /* C, T, E */
ecc_mod_mul (&ecc->p, C, C, z1, x3);
ecc_mod_sqr (&ecc->p, B, z1, x3); /* C, T, E, B */
ecc_mod_add (&ecc->p, x3, B, E);
ecc_mod_sub (&ecc->p, F, B, E); /* C, T, F */
/* Can now use y3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, y3, C, F, y3); /* T G */
/* Can use C--D as scratch */
ecc_mod_mul (&ecc->p, z3, x3, F, C); /* T */
ecc_mod_mul (&ecc->p, x3, x3, T, C);
}
/* ecc-add-thh.c
Copyright (C) 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
/* Add two points on an Edwards curve, in homogeneous coordinates */
void
ecc_add_thh (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 q
#define y2 (q + ecc->p.size)
#define z2 (q + 2*ecc->p.size)
#define x3 r
#define y3 (r + ecc->p.size)
#define z3 (r + 2*ecc->p.size)
/* Formulas (from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#addition-add-2008-bbjlp):
Computation Operation Live variables
C = x1*x2 mul C
D = y1*y2 mul C, D
T = (x1+y1)(x2+y2) - C - D, mul C, D, T
E = b*C*D 2 mul C, E, T (Replace C <-- D - C)
A = z1*z2 mul A, C, E, T
B = A^2 sqr A, B, C, E, T
F = B - E A, B, C, E, F, T
G = B + E A, C, F, G, T
x3 = A*F*T 2 mul A, C, G
y3 = A*G*(D+C) 2 mul F, G
z3 = F*G mul
11M + S
We have different sign for E, hence swapping F and G, because our
ecc->b corresponds to -b above.
*/
#define T scratch
#define E (scratch + 1*ecc->p.size)
#define F E
#define C (scratch + 2*ecc->p.size)
#define D (scratch + 3*ecc->p.size)
#define B D
/* Use T as scratch, clobber E */
ecc_mod_mul (&ecc->p, C, x1, x2, T); /* C */
ecc_mod_mul (&ecc->p, D, y1, y2, T); /* C, D */
ecc_mod_add (&ecc->p, x3, x1, y1);
ecc_mod_add (&ecc->p, y3, x2, y2);
ecc_mod_mul (&ecc->p, T, x3, y3, T); /* C, D, T */
/* Can now use x3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, E, C, D, x3); /* C, D, T, E */
ecc_mod_mul (&ecc->p, E, E, ecc->b, x3);
ecc_mod_add (&ecc->p, C, D, C); /* C, T, E */
ecc_mod_sub (&ecc->p, T, T, C);
ecc_mod_mul (&ecc->p, B, z1, z2, x3);
ecc_mod_mul (&ecc->p, T, T, B, x3);
ecc_mod_mul (&ecc->p, C, C, B, x3);
ecc_mod_sqr (&ecc->p, B, B, x3);
ecc_mod_add (&ecc->p, x3, B, E);
ecc_mod_sub (&ecc->p, F, B, E); /* C, T, F */
/* Can now use y3 as scratch, without breaking in-place operation. */
ecc_mod_mul (&ecc->p, y3, C, F, y3); /* T G */
/* Can use C--D as scratch */
ecc_mod_mul (&ecc->p, z3, x3, F, C); /* T */
ecc_mod_mul (&ecc->p, x3, x3, T, C);
}
/* ecc-curve.h
Copyright (C) 2013 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
/* Development of Nettle's ECC support was funded by the .SE Internet Fund. */
#ifndef NETTLE_ECC_CURVE_H_INCLUDED
#define NETTLE_ECC_CURVE_H_INCLUDED
#include "nettle-types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* The contents of this struct is internal. */
struct ecc_curve;
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_gost_gc256b(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_gost_gc512a(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_192r1(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_224r1(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_256r1(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_384r1(void);
const struct ecc_curve * _NETTLE_ATTRIBUTE_PURE nettle_get_secp_521r1(void);
#ifdef __cplusplus
}
#endif
#endif /* NETTLE_ECC_CURVE_H_INCLUDED */
/* ecc-curve25519.c
Arithmetic and tables for curve25519,
Copyright (C) 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include "ecc-internal.h"
#define USE_REDC 0
#include "ecc-curve25519.h"
#define PHIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 255)
#if HAVE_NATIVE_ecc_curve25519_modp
#define ecc_curve25519_modp _nettle_ecc_curve25519_modp
void
ecc_curve25519_modp (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp);
#else
#if PHIGH_BITS == 0
#error Unsupported limb size */
#endif
static void
ecc_curve25519_modp(const struct ecc_modulo *m UNUSED, mp_limb_t *rp, mp_limb_t *xp)
{
mp_limb_t hi, cy;
cy = mpn_addmul_1 (xp, xp + ECC_LIMB_SIZE, ECC_LIMB_SIZE,
(mp_limb_t) 19 << PHIGH_BITS);
hi = xp[ECC_LIMB_SIZE-1];
cy = (cy << PHIGH_BITS) + (hi >> (GMP_NUMB_BITS - PHIGH_BITS));
rp[ECC_LIMB_SIZE-1] = (hi & (GMP_NUMB_MASK >> PHIGH_BITS))
+ sec_add_1 (rp, xp, ECC_LIMB_SIZE - 1, 19 * cy);
}
#endif /* HAVE_NATIVE_ecc_curve25519_modp */
#define QHIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 252)
#if QHIGH_BITS == 0
#error Unsupported limb size */
#endif
static void
ecc_curve25519_modq (const struct ecc_modulo *q, mp_limb_t *rp, mp_limb_t *xp)
{
mp_size_t n;
mp_limb_t cy;
/* n is the offset where we add in the next term */
for (n = ECC_LIMB_SIZE; n-- > 0;)
{
cy = mpn_submul_1 (xp + n,
q->B_shifted, ECC_LIMB_SIZE,
xp[n + ECC_LIMB_SIZE]);
/* Top limb of mBmodq_shifted is zero, so we get cy == 0 or 1 */
assert_maybe (cy < 2);
mpn_cnd_add_n (cy, xp+n, xp+n, q->m, ECC_LIMB_SIZE);
}
cy = mpn_submul_1 (xp, q->m, ECC_LIMB_SIZE,
xp[ECC_LIMB_SIZE-1] >> (GMP_NUMB_BITS - QHIGH_BITS));
assert_maybe (cy < 2);
mpn_cnd_add_n (cy, rp, xp, q->m, ECC_LIMB_SIZE);
}
/* Computes a^{(p-5)/8} = a^{2^{252}-3} mod m. Needs 4 * n scratch
space. */
static void
ecc_mod_pow_252m3 (const struct ecc_modulo *m,
mp_limb_t *rp, const mp_limb_t *ap, mp_limb_t *scratch)
{
#define a7 scratch
#define t0 (scratch + ECC_LIMB_SIZE)
#define tp (scratch + 2*ECC_LIMB_SIZE)
/* a^{2^252 - 3} = a^{(p-5)/8}, using the addition chain
2^252 - 3
= 1 + (2^252-4)
= 1 + 4 (2^250-1)
= 1 + 4 (2^125+1)(2^125-1)
= 1 + 4 (2^125+1)(1+2(2^124-1))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^62-1))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(2^31-1))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^28-1)))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^14-1)))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^7+1)(2^7-1)))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^7+1)(1+2(2^6-1))))
= 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^7+1)(1+2(2^3+1)*7)))
*/
ecc_mod_pow_2kp1 (m, a7, ap, 1, tp); /* a^3 */
ecc_mod_sqr (m, a7, a7, tp); /* a^6 */
ecc_mod_mul (m, a7, a7, ap, tp); /* a^7 */
ecc_mod_pow_2kp1 (m, rp, a7, 3, tp); /* a^63 = a^{2^6-1} */
ecc_mod_sqr (m, rp, rp, tp); /* a^{2^7-2} */
ecc_mod_mul (m, rp, rp, ap, tp); /* a^{2^7-1} */
ecc_mod_pow_2kp1 (m, t0, rp, 7, tp); /* a^{2^14-1}*/
ecc_mod_pow_2kp1 (m, rp, t0, 14, tp); /* a^{2^28-1} */
ecc_mod_sqr (m, rp, rp, tp); /* a^{2^29-2} */
ecc_mod_sqr (m, rp, rp, tp); /* a^{2^30-4} */
ecc_mod_sqr (m, rp, rp, tp); /* a^{2^31-8} */
ecc_mod_mul (m, rp, rp, a7, tp); /* a^{2^31-1} */
ecc_mod_pow_2kp1 (m, t0, rp, 31, tp); /* a^{2^62-1} */
ecc_mod_pow_2kp1 (m, rp, t0, 62, tp); /* a^{2^124-1}*/
ecc_mod_sqr (m, rp, rp, tp); /* a^{2^125-2} */
ecc_mod_mul (m, rp, rp, ap, tp); /* a^{2^125-1} */
ecc_mod_pow_2kp1 (m, t0, rp, 125, tp);/* a^{2^250-1} */
ecc_mod_sqr (m, rp, t0, tp); /* a^{2^251-2} */
ecc_mod_sqr (m, rp, rp, tp); /* a^{2^252-4} */
ecc_mod_mul (m, rp, rp, ap, tp); /* a^{2^252-3} */
#undef a7
#undef t0
#undef tp
}
/* Scratch as for ecc_mod_pow_252m3 above. */
#define ECC_25519_INV_ITCH (4*ECC_LIMB_SIZE)
static void
ecc_curve25519_inv (const struct ecc_modulo *p,
mp_limb_t *rp, const mp_limb_t *ap,
mp_limb_t *scratch)
{
/* Addition chain
p - 2 = 2^{255} - 21
= 1 + 2 (1 + 4 (2^{252}-3))
*/
ecc_mod_pow_252m3 (p, rp, ap, scratch);
ecc_mod_sqr (p, rp, rp, scratch);
ecc_mod_sqr (p, rp, rp, scratch);
ecc_mod_mul (p, rp, ap, rp, scratch);
ecc_mod_sqr (p, rp, rp, scratch);
ecc_mod_mul (p, rp, ap, rp, scratch);
}
static int
ecc_curve25519_zero_p (const struct ecc_modulo *p, mp_limb_t *xp)
{
/* First, reduce to < 2p. */
#if PHIGH_BITS > 0
mp_limb_t hi = xp[ECC_LIMB_SIZE-1];
xp[ECC_LIMB_SIZE-1] = (hi & (GMP_NUMB_MASK >> PHIGH_BITS))
+ sec_add_1 (xp, xp, ECC_LIMB_SIZE - 1, 19 * (hi >> (GMP_NUMB_BITS - PHIGH_BITS)));
#endif
return ecc_mod_zero_p (p, xp);
}
/* Compute x such that x^2 = u/v (mod p). Returns one on success, zero
on failure. We use the e = 2 special case of the Shanks-Tonelli
algorithm (see http://www.math.vt.edu/people/brown/doc/sqrts.pdf,
or Henri Cohen, Computational Algebraic Number Theory, 1.5.1).
To avoid a separate inversion, we also use a trick of djb's, to
compute the candidate root as
x = (u/v)^{(p+3)/8} = u v^3 (u v^7)^{(p-5)/8}.
*/
#if ECC_SQRT_E != 2
#error Broken curve25519 parameters
#endif
/* Needs 2*n space + scratch for ecc_mod_pow_252m3. */
#define ECC_25519_SQRT_RATIO_ITCH (6*ECC_LIMB_SIZE)
static int
ecc_curve25519_sqrt_ratio(const struct ecc_modulo *p, mp_limb_t *rp,
const mp_limb_t *up, const mp_limb_t *vp,
mp_limb_t *scratch)
{
int pos, neg;
#define uv3 scratch
#define uv7 (scratch + ECC_LIMB_SIZE)
#define v2 uv7
#define uv uv3
#define v4 uv7
#define scratch_out (scratch + 2 * ECC_LIMB_SIZE)
#define x2 scratch
#define vx2 (scratch + ECC_LIMB_SIZE)
#define t0 (scratch + 2*ECC_LIMB_SIZE)
/* Live values */
ecc_mod_sqr (p, v2, vp, scratch_out); /* v2 */
ecc_mod_mul (p, uv, up, vp, scratch_out); /* uv, v2 */
ecc_mod_mul (p, uv3, uv, v2, scratch_out); /* uv3, v2 */
ecc_mod_sqr (p, v4, v2, scratch_out); /* uv3, v4 */
ecc_mod_mul (p, uv7, uv3, v4, scratch_out); /* uv7 */
ecc_mod_pow_252m3 (p, rp, uv7, scratch_out); /* uv3, uv7p */
ecc_mod_mul (p, rp, rp, uv3, scratch_out); /* none */
/* Check sign. If square root exists, have v x^2 = ±u */
ecc_mod_sqr (p, x2, rp, t0);
ecc_mod_mul (p, vx2, x2, vp, t0);
ecc_mod_add (p, t0, vx2, up);
neg = ecc_curve25519_zero_p (p, t0);
ecc_mod_sub (p, t0, up, vx2);
pos = ecc_curve25519_zero_p (p, t0);
ecc_mod_mul (p, t0, rp, ecc_sqrt_z, t0);
cnd_copy (neg, rp, t0, ECC_LIMB_SIZE);
return pos | neg;
#undef uv3
#undef uv7
#undef v2
#undef uv
#undef v4
#undef scratch_out
#undef x2
#undef vx2
#undef t0
}
const struct ecc_curve _nettle_curve25519 =
{
{
255,
ECC_LIMB_SIZE,
ECC_BMODP_SIZE,
0,
ECC_25519_INV_ITCH,
0,
ECC_25519_SQRT_RATIO_ITCH,
ecc_p,
ecc_Bmodp,
ecc_Bmodp_shifted,
ecc_Bm2p,
NULL,
ecc_pp1h,
ecc_curve25519_modp,
ecc_curve25519_modp,
ecc_curve25519_inv,
NULL,
ecc_curve25519_sqrt_ratio,
},
{
253,
ECC_LIMB_SIZE,
ECC_BMODQ_SIZE,
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
ecc_mBmodq_shifted, /* Use q - 2^{252} instead. */
ecc_Bm2q,
NULL,
ecc_qp1h,
ecc_curve25519_modq,
ecc_curve25519_modq,
ecc_mod_inv,
NULL,
NULL,
},
0, /* No redc */
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
ECC_ADD_TH_ITCH (ECC_LIMB_SIZE),
ECC_ADD_THH_ITCH (ECC_LIMB_SIZE),
ECC_DUP_TH_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_EH_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_EH_ITCH (ECC_LIMB_SIZE),
ECC_EH_TO_A_ITCH (ECC_LIMB_SIZE, ECC_25519_INV_ITCH),
ecc_add_th,
ecc_add_thh,
ecc_dup_th,
ecc_mul_a_eh,
ecc_mul_g_eh,
ecc_eh_to_a,
ecc_b, /* Edwards curve constant. */
ecc_unit,
ecc_table
};
/* ecc-curve448.c
Arithmetic and tables for curve448,
Copyright (C) 2017 Daiki Ueno
Copyright (C) 2017 Red Hat, Inc.
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include "ecc-internal.h"
#define USE_REDC 0
#include "ecc-curve448.h"
#if HAVE_NATIVE_ecc_curve448_modp
#define ecc_curve448_modp _nettle_ecc_curve448_modp
void
ecc_curve448_modp (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp);
#elif GMP_NUMB_BITS == 64
static void
ecc_curve448_modp(const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp)
{
/* Let B = 2^64, b = 2^32 = sqrt(B).
p = B^7 - b B^3 - 1 ==> B^7 = b B^3 + 1
We use this to reduce
{r_{13}, ..., r_0} =
{r_6,...,r_0}
+ {r_{10},...,r_7}
+ 2 {r_{13},r_{12}, r_{11}} B^4
+ b {r_{10},...,r_7,r_{13},r_{12},r_{11} (mod p)
or
+----+----+----+----+----+----+----+
|r_6 |r_5 |r_4 |r_3 |r_2 |r_1 |r_0 |
+----+----+----+----+----+----+----+
|r_10|r_9 |r_8 |r_7 |
+----+----+----+----+----+----+----+
2 * |r_13|r_12|r_11|
+----+----+----+----+----+----+----+
+ b * |r_10|r_9 |r_8 |r_7 |r_13|r_12|r_11|
-------+----+----+----+----+----+----+----+
c_7 |r_6 |r_5 |r_4 |r_3 |r_2 |r_1 |r_0 |
+----+----+----+----+----+----+----+
*/
mp_limb_t c3, c4, c7;
mp_limb_t *tp = xp + 7;
c4 = mpn_add_n (xp, xp, xp + 7, 4);
c7 = mpn_addmul_1 (xp + 4, xp + 11, 3, 2);
c3 = mpn_addmul_1 (xp, xp + 11, 3, (mp_limb_t) 1 << 32);
c7 += mpn_addmul_1 (xp + 3, xp + 7, 4, (mp_limb_t) 1 << 32);
tp[0] = c7;
tp[1] = tp[2] = 0;
tp[3] = c3 + (c7 << 32);
tp[4] = c4 + (c7 >> 32) + (tp[3] < c3);
tp[5] = tp[6] = 0;
c7 = mpn_add_n (rp, xp, tp, 7);
c7 = mpn_cnd_add_n (c7, rp, rp, m->B, 7);
assert_maybe (c7 == 0);
}
#else
#define ecc_curve448_modp ecc_mod
#endif
/* Computes a^{(p-3)/4} = a^{2^446-2^222-1} mod m. Needs 4 * n scratch
space. */
static void
ecc_mod_pow_446m224m1 (const struct ecc_modulo *p,
mp_limb_t *rp, const mp_limb_t *ap,
mp_limb_t *scratch)
{
/* Note overlap: operations writing to t0 clobber t1. */
#define t0 scratch
#define t1 (scratch + ECC_LIMB_SIZE)
#define tp (scratch + 2*ECC_LIMB_SIZE)
/* Set t0 = a^7 */
ecc_mod_sqr (p, t0, ap, tp); /* a^2 */
ecc_mod_mul (p, t0, ap, t0, tp); /* a^3 */
ecc_mod_sqr (p, t0, t0, tp); /* a^6 */
ecc_mod_mul (p, t0, ap, t0, tp); /* a^{2^3-1} */
/* Set t0 = a^{2^18-1} */
ecc_mod_pow_2kp1 (p, rp, t0, 3, tp); /* a^{2^6-1} */
ecc_mod_pow_2k (p, rp, rp, 3, tp); /* a^{2^9-2^3} */
ecc_mod_mul (p, rp, rp, t0, tp); /* a^{2^9-1} */
ecc_mod_pow_2kp1 (p, t0, rp, 9, tp); /* a^{2^18-1} */
/* Set t0 = a^{2^37-1} */
ecc_mod_sqr (p, rp, t0, tp); /* a^{2^19-2} */
ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^19-1} */
ecc_mod_pow_2k (p, t1, rp, 18, tp); /* a^{2^37-2^18} */
ecc_mod_mul (p, t0, t0, t1, tp); /* a^{2^37-1} */
/* Set t0 = a^{2^222-1} */
ecc_mod_pow_2kp1 (p, rp, t0, 37, tp); /* a^{2^74-1} */
ecc_mod_pow_2k (p, t1, rp, 37, tp); /* a^{2^111-2^37} */
ecc_mod_mul (p, t1, t1, t0, tp); /* a^{2^111-1} */
ecc_mod_pow_2kp1 (p, t0, t1, 111, tp);/* a^{2^222-1} */
ecc_mod_sqr (p, rp, t0, tp); /* a^{2^223-2} */
ecc_mod_mul (p, rp, rp, ap, tp); /* a^{2^223-1} */
ecc_mod_pow_2k (p, t1, rp, 223, tp); /* a^{2^446-2^223} */
ecc_mod_mul (p, rp, t1, t0, tp); /* a^{2^446-2^222-1} */
#undef t0
#undef t1
#undef tp
}
#define ECC_CURVE448_INV_ITCH (4*ECC_LIMB_SIZE)
static void ecc_curve448_inv (const struct ecc_modulo *p,
mp_limb_t *rp, const mp_limb_t *ap,
mp_limb_t *tp)
{
ecc_mod_pow_446m224m1 (p, rp, ap, tp);/* a^{2^446-2^222-1} */
ecc_mod_sqr (p, rp, rp, tp); /* a^{2^447-2^223-2} */
ecc_mod_sqr (p, rp, rp, tp); /* a^{2^448-2^224-4} */
ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^448-2^224-3} */
}
/* To guarantee that inputs to ecc_mod_zero_p are in the required range. */
#if ECC_LIMB_SIZE * GMP_NUMB_BITS != 448
#error Unsupported limb size
#endif
/* Compute x such that x^2 = u/v (mod p). Returns one on success, zero
on failure.
To avoid a separate inversion, we use a trick of djb's, to
compute the candidate root as
x = (u/v)^{(p+1)/4} = u^3 v (u^5 v^3)^{(p-3)/4}.
*/
/* Needs 2*n space + scratch for ecc_mod_pow_446m224m1. */
#define ECC_CURVE448_SQRT_RATIO_ITCH (6*ECC_LIMB_SIZE)
static int
ecc_curve448_sqrt_ratio(const struct ecc_modulo *p, mp_limb_t *rp,
const mp_limb_t *up, const mp_limb_t *vp,
mp_limb_t *scratch)
{
#define uv scratch
#define u3v (scratch + ECC_LIMB_SIZE)
#define u5v3 uv
#define t0 scratch
#define scratch_out (scratch + 2*ECC_LIMB_SIZE)
/* Live values */
ecc_mod_mul (p, uv, up, vp, scratch_out); /* uv */
ecc_mod_sqr (p, u3v, up, scratch_out); /* uv, u3v */
ecc_mod_mul (p, u3v, u3v, uv, scratch_out); /* uv, u3v */
ecc_mod_sqr (p, u5v3, uv, scratch_out); /* u5v3, u3v */
ecc_mod_mul (p, u5v3, u5v3, u3v, scratch_out);/* u5v3, u3v */
ecc_mod_pow_446m224m1 (p, rp, u5v3, scratch_out); /* u3v */
ecc_mod_mul (p, rp, rp, u3v, scratch_out);
/* If square root exists, have v x^2 = u */
ecc_mod_sqr (p, t0, rp, scratch_out); /* x^2 */
ecc_mod_mul (p, t0, t0, vp, scratch_out); /* v x^2 */
ecc_mod_sub (p, t0, t0, up);
return ecc_mod_zero_p (p, t0);
#undef uv
#undef u3v
#undef u5v3
#undef t0
#undef scratch_out
}
const struct ecc_curve _nettle_curve448 =
{
{
448,
ECC_LIMB_SIZE,
ECC_BMODP_SIZE,
0,
ECC_CURVE448_INV_ITCH,
0,
ECC_CURVE448_SQRT_RATIO_ITCH,
ecc_p,
ecc_Bmodp,
ecc_Bmodp_shifted,
ecc_Bm2p,
NULL,
ecc_pp1h,
ecc_curve448_modp,
ecc_curve448_modp,
ecc_curve448_inv,
NULL,
ecc_curve448_sqrt_ratio,
},
{
446,
ECC_LIMB_SIZE,
ECC_BMODQ_SIZE,
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
ecc_Bmodq_shifted,
ecc_Bm2q,
NULL,
ecc_qp1h,
ecc_mod,
ecc_mod,
ecc_mod_inv,
NULL,
NULL,
},
0, /* No redc */
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
ECC_ADD_EH_ITCH (ECC_LIMB_SIZE),
ECC_ADD_EHH_ITCH (ECC_LIMB_SIZE),
ECC_DUP_EH_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_EH_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_EH_ITCH (ECC_LIMB_SIZE),
ECC_EH_TO_A_ITCH (ECC_LIMB_SIZE, ECC_CURVE448_INV_ITCH),
ecc_add_eh,
ecc_add_ehh,
ecc_dup_eh,
ecc_mul_a_eh,
ecc_mul_g_eh,
ecc_eh_to_a,
ecc_b,
ecc_unit,
ecc_table
};
/* ecc-dup-eh.c
Copyright (C) 2014 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "ecc.h"
#include "ecc-internal.h"
/* Double a point on an Edwards curve, in homogeneous coordinates */
void
ecc_dup_eh (const struct ecc_curve *ecc,
mp_limb_t *r, const mp_limb_t *p,
mp_limb_t *scratch)
{
#define x1 p
#define y1 (p + ecc->p.size)
#define z1 (p + 2*ecc->p.size)
#define x2 r
#define y2 (r + ecc->p.size)
#define z2 (r + 2*ecc->p.size)
/* Formulas (from djb,
http://www.hyperelliptic.org/EFD/g1p/auto-edwards-projective.html#doubling-dbl-2007-bl):
Computation Operation Live variables
b = (x+y)^2 sqr b
c = x^2 sqr b, c
d = y^2 sqr b, c, d
e = c+d b, c, d, e
h = z^2 sqr b, c, d, e, h
j = e-2*h b, c, d, e, j
x' = (b-e)*j mul c, d, e, j
y' = e*(c-d) mul e, j
z' = e*j mul
*/
#define C scratch
#define D (scratch + 1*ecc->p.size)
#define B (scratch + 2*ecc->p.size)
#define E C
ecc_mod_sqr (&ecc->p, C, x1, C); /* C */
ecc_mod_sqr (&ecc->p, D, y1, D); /* C, D */
ecc_mod_add (&ecc->p, B, x1, y1);
ecc_mod_sqr (&ecc->p, B, B, x2); /* C, D, B */
/* c-d stored at y' */
ecc_mod_sub (&ecc->p, y2, C, D);
ecc_mod_add (&ecc->p, E, C, D); /* B, E */
/* b-e stored at x' */
ecc_mod_sub (&ecc->p, x2, B, E); /* E */
/* Use D as scratch for the following multiplies. */
ecc_mod_mul (&ecc->p, y2, y2, E, D);
/* h and j stored at z' */
ecc_mod_sqr (&ecc->p, z2, z1, D);
ecc_mod_add (&ecc->p, z2, z2, z2);
ecc_mod_sub (&ecc->p, z2, E, z2);
ecc_mod_mul (&ecc->p, x2, x2, z2, D);
ecc_mod_mul (&ecc->p, z2, z2, E, D);
}