Update chopstx to 1.1
[gnuk/gnuk.git] / src / call-ec.c
1 /*
2  * call-ec.c - interface between Gnuk and Elliptic curve over GF(prime)
3  *
4  * Copyright (C) 2013, 2014 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "field-group-select.h"
25
26 /* We are little-endian in the computation, but the protocol is big-endian.  */
27
28 #define ECDSA_BYTE_SIZE 32
29 #define ECDH_BYTE_SIZE 32
30
31 int
32 FUNC(ecdsa_sign) (const uint8_t *hash, uint8_t *output,
33                   const uint8_t *key_data)
34 {
35   int i;
36   bn256 r[1], s[1], z[1], d[1];
37   uint8_t *p;
38
39   p = (uint8_t *)d;
40   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
41     p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
42
43   p = (uint8_t *)z;
44   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
45     p[ECDSA_BYTE_SIZE - i - 1] = hash[i];
46
47   FUNC(ecdsa) (r, s, z, d);
48   p = (uint8_t *)r;
49   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
50     *output++ = p[ECDSA_BYTE_SIZE - i - 1];
51   p = (uint8_t *)s;
52   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
53     *output++ = p[ECDSA_BYTE_SIZE - i - 1];
54   return 0;
55 }
56
57 uint8_t *
58 FUNC(ecc_compute_public) (const uint8_t *key_data)
59 {
60   uint8_t *p0, *p, *p1;
61   ac q[1];
62   bn256 k[1];
63   int i;
64
65   p0 = (uint8_t *)malloc (ECDSA_BYTE_SIZE * 2);
66   if (p0 == NULL)
67     return NULL;
68
69   p = (uint8_t *)k;
70   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
71     p[ECDSA_BYTE_SIZE - i - 1] = key_data[i];
72   if (FUNC(compute_kG) (q, k) < 0)
73     {
74       free (p0);
75       return NULL;
76     }
77
78   p = p0;
79   p1 = (uint8_t *)q->x;
80   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
81     *p++ = p1[ECDSA_BYTE_SIZE - i - 1];
82   p1 = (uint8_t *)q->y;
83   for (i = 0; i < ECDSA_BYTE_SIZE; i++)
84     *p++ = p1[ECDSA_BYTE_SIZE - i - 1];
85
86   return p0;
87 }
88
89 int
90 FUNC(ecdh_decrypt) (const uint8_t *input, uint8_t *output,
91                     const uint8_t *key_data)
92 {
93   bn256 k[1];
94   ac X[1], P[1];
95   int i;
96   uint8_t *p0;
97   const uint8_t *p1;
98   int r;
99
100   p0 = (uint8_t *)k;
101   for (i = 0; i < ECDH_BYTE_SIZE; i++)
102     p0[ECDH_BYTE_SIZE - i - 1] = key_data[i];
103
104   p1 = input+1;                 /* skip '04' */
105   p0 = (uint8_t *)P->x;
106   for (i = 0; i < ECDH_BYTE_SIZE; i++)
107     p0[ECDH_BYTE_SIZE - i - 1] = *p1++;
108   p0 = (uint8_t *)P->y;
109   for (i = 0; i < ECDH_BYTE_SIZE; i++)
110     p0[ECDH_BYTE_SIZE - i - 1] = *p1++;
111
112   r = FUNC(compute_kP) (X, k, P);
113   if (r == 0)
114     {
115       p0 = output;
116       p1 = (const uint8_t *)X->x;
117       *p0++ = 4;
118       for (i = 0; i < ECDH_BYTE_SIZE; i++)
119         *p0++ = p1[ECDH_BYTE_SIZE - i - 1];
120       p1 = (const uint8_t *)X->y;
121       for (i = 0; i < ECDH_BYTE_SIZE; i++)
122         *p0++ = p1[ECDH_BYTE_SIZE - i - 1];
123     }
124
125   return r;
126 }
127
128
129 /**
130  * @brief Check if a secret d0 is valid or not
131  *
132  * @param D0    scalar D0: secret
133  * @param D1    scalar D1: secret candidate N-D0
134  *
135  * Return 0 on error.
136  * Return -1 when D1 should be used as the secret
137  * Return 1 when D0 should be used as the secret
138  */
139 int
140 FUNC(ecc_check_secret) (const uint8_t *d0, uint8_t *d1)
141 {
142   return FUNC(check_secret) ((const bn256 *)d0, (bn256 *)d1);
143 }