/src/nettle/gostdsa-vko.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* gostdsa-vko.c |
2 | | |
3 | | Copyright (C) 2016 Dmitry Eremin-Solenikov |
4 | | |
5 | | This file is part of GNU Nettle. |
6 | | |
7 | | GNU Nettle is free software: you can redistribute it and/or |
8 | | modify it under the terms of either: |
9 | | |
10 | | * the GNU Lesser General Public License as published by the Free |
11 | | Software Foundation; either version 3 of the License, or (at your |
12 | | option) any later version. |
13 | | |
14 | | or |
15 | | |
16 | | * the GNU General Public License as published by the Free |
17 | | Software Foundation; either version 2 of the License, or (at your |
18 | | option) any later version. |
19 | | |
20 | | or both in parallel, as here. |
21 | | |
22 | | GNU Nettle is distributed in the hope that it will be useful, |
23 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
25 | | General Public License for more details. |
26 | | |
27 | | You should have received copies of the GNU General Public License and |
28 | | the GNU Lesser General Public License along with this program. If |
29 | | not, see http://www.gnu.org/licenses/. |
30 | | */ |
31 | | |
32 | | #if HAVE_CONFIG_H |
33 | | # include "config.h" |
34 | | #endif |
35 | | |
36 | | #include <assert.h> |
37 | | #include <stdlib.h> |
38 | | |
39 | | #include "ecc-internal.h" |
40 | | #include "gostdsa.h" |
41 | | |
42 | | /* |
43 | | * Shared key derivation/key agreement for GOST DSA algorithm. |
44 | | * It is defined in RFC 4357 Section 5.2 and RFC 7836 Section 4.3.1 |
45 | | * |
46 | | * output is 2 * curve size: |
47 | | * 64 bytes for 256 bit curves and 128 bytes for 512 bit ones |
48 | | * |
49 | | * Basically shared key is equal to hash(cofactor * ukm * priv * pub). This |
50 | | * function does multiplication. Caller should do hashing on his own. |
51 | | * |
52 | | * UKM is not a secret value (consider it as a nonce). |
53 | | * |
54 | | * For supported GOST curves cofactor is equal to 1. |
55 | | */ |
56 | | void |
57 | | gostdsa_vko (const struct ecc_scalar *priv, |
58 | | const struct ecc_point *pub, |
59 | | size_t ukm_length, const uint8_t *ukm, |
60 | | uint8_t *out) |
61 | 0 | { |
62 | 0 | const struct ecc_curve *ecc = priv->ecc; |
63 | 0 | unsigned bsize = (ecc_bit_size (ecc) + 7) / 8; |
64 | 0 | mp_size_t size = ecc->p.size; |
65 | 0 | mp_size_t itch = 4*size + ecc->mul_itch; |
66 | 0 | mp_limb_t *scratch; |
67 | |
|
68 | 0 | if (itch < 5*size + ecc->h_to_a_itch) |
69 | 0 | itch = 5*size + ecc->h_to_a_itch; |
70 | |
|
71 | 0 | assert (pub->ecc == ecc); |
72 | 0 | assert (priv->ecc == ecc); |
73 | 0 | assert (ukm_length <= bsize); |
74 | | |
75 | 0 | scratch = gmp_alloc_limbs (itch); |
76 | |
|
77 | 0 | #define UKM scratch |
78 | 0 | #define TEMP (scratch + 3*size) |
79 | 0 | #define XYZ scratch |
80 | 0 | #define TEMP_Y (scratch + 4*size) |
81 | |
|
82 | 0 | mpn_set_base256_le (UKM, size, ukm, ukm_length); |
83 | | |
84 | | /* If ukm is 0, set it to 1, otherwise the result will be allways equal to 0, |
85 | | * no matter what private and public keys are. See RFC 4357 referencing GOST |
86 | | * R 34.10-2001 (RFC 5832) Section 6.1 step 2. */ |
87 | 0 | if (mpn_zero_p (UKM, size)) |
88 | 0 | UKM[0] = 1; |
89 | |
|
90 | 0 | ecc_mod_mul_canonical (&ecc->q, TEMP, priv->p, UKM, TEMP); /* TEMP = UKM * priv */ |
91 | 0 | ecc->mul (ecc, XYZ, TEMP, pub->p, scratch + 4*size); /* XYZ = UKM * priv * pub */ |
92 | 0 | ecc->h_to_a (ecc, 0, TEMP, XYZ, scratch + 5*size); /* TEMP = XYZ */ |
93 | 0 | mpn_get_base256_le (out, bsize, TEMP, size); |
94 | 0 | mpn_get_base256_le (out+bsize, bsize, TEMP_Y, size); |
95 | 0 | gmp_free_limbs (scratch, itch); |
96 | 0 | } |