1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
*
* All curves taken from NIST recommendation paper of July 1999
* Available at http://csrc.nist.gov/cryptval/dss.htm
*/
#include "tomcrypt.h"
/**
@file ecc_make_key.c
ECC Crypto, Tom St Denis
*/
#ifdef LTC_MECC
/**
Make a new ECC key
@param prng An active PRNG state
@param wprng The index of the PRNG you wish to use
@param keysize The keysize for the new key (in octets from 20 to 65 bytes)
@param key [out] Destination of the newly created key
@return CRYPT_OK if successful, upon error all allocated memory will be freed
*/
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
{
int x, err;
/* find key size */
for (x = 0; (keysize > ltc_ecc_sets[x].size) && (ltc_ecc_sets[x].size != 0); x++);
keysize = ltc_ecc_sets[x].size;
if (keysize > ECC_MAXSIZE || ltc_ecc_sets[x].size == 0) {
return CRYPT_INVALID_KEYSIZE;
}
err = ecc_make_key_ex(prng, wprng, key, <c_ecc_sets[x]);
key->idx = x;
return err;
}
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp)
{
int err;
ecc_point *base;
void *prime, *order;
unsigned char *buf;
int keysize;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
LTC_ARGCHK(dp != NULL);
/* good prng? */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
key->idx = -1;
key->dp = dp;
keysize = dp->size;
/* allocate ram */
base = NULL;
buf = XMALLOC(ECC_MAXSIZE);
if (buf == NULL) {
return CRYPT_MEM;
}
/* make up random string */
if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
err = CRYPT_ERROR_READPRNG;
goto ERR_BUF;
}
/* setup the key variables */
if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, NULL)) != CRYPT_OK) {
goto ERR_BUF;
}
base = ltc_ecc_new_point();
if (base == NULL) {
err = CRYPT_MEM;
goto errkey;
}
/* read in the specs for this key */
if ((err = mp_read_radix(prime, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto errkey; }
if ((err = mp_read_radix(order, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errkey; }
if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto errkey; }
if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto errkey; }
if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto errkey; }
if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) { goto errkey; }
/* the key should be smaller than the order of base point */
if (mp_cmp(key->k, order) != LTC_MP_LT) {
if((err = mp_mod(key->k, order, key->k)) != CRYPT_OK) { goto errkey; }
}
/* make the public key */
if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK) { goto errkey; }
key->type = PK_PRIVATE;
/* free up ram */
err = CRYPT_OK;
goto cleanup;
errkey:
mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
cleanup:
ltc_ecc_del_point(base);
mp_clear_multi(prime, order, NULL);
ERR_BUF:
#ifdef LTC_CLEAN_STACK
zeromem(buf, ECC_MAXSIZE);
#endif
XFREE(buf);
return err;
}
#endif
/* $Source$ */
/* $Revision$ */
/* $Date$ */
|