updated makefiles
[gnutls.git] / lib / nettle / ecc_projective_dbl_point_3.c
blob1b376fe6d157967018a418c5a681e07a02f41600
1 /*
2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 3 of
9 * the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
21 /* Based on public domain code of LibTomCrypt by Tom St Denis.
22 * Adapted to gmp and nettle by Nikos Mavrogiannopoulos.
25 #include "ecc.h"
28 @file ecc_projective_dbl_point.c
29 ECC Crypto, Tom St Denis
30 */
32 #ifdef ECC_SECP_CURVES_ONLY
35 Double an ECC point
36 @param P The point to double
37 @param R [out] The destination of the double
38 @param modulus The modulus of the field the ECC curve is in
39 @param mp The "b" value from montgomery_setup()
40 @return 0 on success
42 int
43 ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a /* a is -3 */,
44 mpz_t modulus)
46 mpz_t t1, t2;
47 int err;
49 if (P == NULL || R == NULL || modulus == NULL)
50 return -1;
52 if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
53 return err;
56 if (P != R) {
57 mpz_set(R->x, P->x);
58 mpz_set(R->y, P->y);
59 mpz_set(R->z, P->z);
62 /* t1 = Z * Z */
63 mpz_mul(t1, R->z, R->z);
64 mpz_mod(t1, t1, modulus);
65 /* Z = Y * Z */
66 mpz_mul(R->z, R->y, R->z);
67 mpz_mod(R->z, R->z, modulus);
68 /* Z = 2Z */
69 mpz_add(R->z, R->z, R->z);
70 if (mpz_cmp(R->z, modulus) >= 0) {
71 mpz_sub(R->z, R->z, modulus);
74 /* T2 = X - T1 */
75 mpz_sub(t2, R->x, t1);
76 if (mpz_cmp_ui(t2, 0) < 0) {
77 mpz_add(t2, t2, modulus);
79 /* T1 = X + T1 */
80 mpz_add(t1, t1, R->x);
81 if (mpz_cmp(t1, modulus) >= 0) {
82 mpz_sub(t1, t1, modulus);
84 /* T2 = T1 * T2 */
85 mpz_mul(t2, t1, t2);
86 mpz_mod(t2, t2, modulus);
87 /* T1 = 2T2 */
88 mpz_add(t1, t2, t2);
89 if (mpz_cmp(t1, modulus) >= 0) {
90 mpz_sub(t1, t1, modulus);
92 /* T1 = T1 + T2 */
93 mpz_add(t1, t1, t2);
94 if (mpz_cmp(t1, modulus) >= 0) {
95 mpz_sub(t1, t1, modulus);
98 /* Y = 2Y */
99 mpz_add(R->y, R->y, R->y);
100 if (mpz_cmp(R->y, modulus) >= 0) {
101 mpz_sub(R->y, R->y, modulus);
103 /* Y = Y * Y */
104 mpz_mul(R->y, R->y, R->y);
105 mpz_mod(R->y, R->y, modulus);
106 /* T2 = Y * Y */
107 mpz_mul(t2, R->y, R->y);
108 mpz_mod(t2, t2, modulus);
109 /* T2 = T2/2 */
110 if (mpz_odd_p(t2)) {
111 mpz_add(t2, t2, modulus);
113 mpz_divexact_ui(t2, t2, 2);
114 /* Y = Y * X */
115 mpz_mul(R->y, R->y, R->x);
116 mpz_mod(R->y, R->y, modulus);
118 /* X = T1 * T1 */
119 mpz_mul(R->x, t1, t1);
120 mpz_mod(R->x, R->x, modulus);
121 /* X = X - Y */
122 mpz_sub(R->x, R->x, R->y);
123 if (mpz_cmp_ui(R->x, 0) < 0) {
124 mpz_add(R->x, R->x, modulus);
126 /* X = X - Y */
127 mpz_sub(R->x, R->x, R->y);
128 if (mpz_cmp_ui(R->x, 0) < 0) {
129 mpz_add(R->x, R->x, modulus);
132 /* Y = Y - X */
133 mpz_sub(R->y, R->y, R->x);
134 if (mpz_cmp_ui(R->y, 0) < 0) {
135 mpz_add(R->y, R->y, modulus);
137 /* Y = Y * T1 */
138 mpz_mul(R->y, R->y, t1);
139 mpz_mod(R->y, R->y, modulus);
140 /* Y = Y - T2 */
141 mpz_sub(R->y, R->y, t2);
142 if (mpz_cmp_ui(R->y, 0) < 0) {
143 mpz_add( R->y, R->y, modulus);
146 err = 0;
148 mp_clear_multi(&t1, &t2, NULL);
149 return err;
151 #endif
152 /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_projective_dbl_point.c,v $ */
153 /* $Revision: 1.11 $ */
154 /* $Date: 2007/05/12 14:32:35 $ */