1 int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
2 unsigned char *out, unsigned long *len,
3 prng_state *prng, int wprng, int hash,
6 unsigned char pub_expt[256], ecc_shared[256], skey[MAXBLOCKSIZE];
8 unsigned long x, y, z, hashsize, pubkeysize;
11 _ARGCHK(inkey != NULL);
16 /* check that wprng/cipher/hash are not invalid */
17 if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
21 if ((err = hash_is_valid(hash)) != CRYPT_OK) {
25 if (keylen > hash_descriptor[hash].hashsize) {
26 return CRYPT_INVALID_HASH;
29 /* make a random key and export the public copy */
30 if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
34 pubkeysize = (unsigned long)sizeof(pub_expt);
35 if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
40 /* now check if the out buffer is big enough */
41 if (*len < (9 + PACKET_SIZE + pubkeysize + hash_descriptor[hash].hashsize)) {
43 return CRYPT_BUFFER_OVERFLOW;
47 hashsize = hash_descriptor[hash].hashsize;
48 x = (unsigned long)sizeof(ecc_shared);
49 if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
54 z = (unsigned long)sizeof(skey);
55 if ((err = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
60 for (x = 0; x < keylen; x++) {
67 /* size of hash name and the name itself */
68 out[y++] = hash_descriptor[hash].ID;
70 /* length of ECC pubkey and the key itself */
71 STORE32L(pubkeysize, out+y);
74 for (x = 0; x < pubkeysize; x++, y++) {
78 STORE32L(keylen, out+y);
81 /* Store the encrypted key */
82 for (x = 0; x < keylen; x++, y++) {
87 packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY);
91 zeromem(pub_expt, sizeof(pub_expt));
92 zeromem(ecc_shared, sizeof(ecc_shared));
93 zeromem(skey, sizeof(skey));
99 int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
100 unsigned char *outkey, unsigned long *keylen,
103 unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
104 unsigned long x, y, z, hashsize, keysize;
109 _ARGCHK(outkey != NULL);
110 _ARGCHK(keylen != NULL);
111 _ARGCHK(key != NULL);
113 /* right key type? */
114 if (key->type != PK_PRIVATE) {
115 return CRYPT_PK_NOT_PRIVATE;
118 /* correct length ? */
119 if (inlen < PACKET_SIZE+1+4+4) {
120 return CRYPT_INVALID_PACKET;
122 inlen -= PACKET_SIZE+1+4+4;
125 /* is header correct? */
126 if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
130 /* now lets get the hash name */
132 hash = find_hash_id(in[y++]);
134 return CRYPT_INVALID_HASH;
138 hashsize = hash_descriptor[hash].hashsize;
143 return CRYPT_INVALID_PACKET;
148 if ((err = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) {
153 /* make shared key */
154 x = (unsigned long)sizeof(shared_secret);
155 if ((err = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
161 z = (unsigned long)sizeof(skey);
162 if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
166 LOAD32L(keysize, in+y);
167 if (inlen < keysize) {
168 return CRYPT_INVALID_PACKET;
174 if (*keylen < keysize) {
175 res = CRYPT_BUFFER_OVERFLOW;
179 /* Decrypt the key */
180 for (x = 0; x < keysize; x++, y++) {
181 outkey[x] = skey[x] ^ in[y];
189 zeromem(shared_secret, sizeof(shared_secret));
190 zeromem(skey, sizeof(skey));
195 int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
196 unsigned char *out, unsigned long *outlen,
197 prng_state *prng, int wprng, ecc_key *key)
201 unsigned char epubkey[256], er[256];
202 unsigned long x, y, pubkeysize, rsize;
206 _ARGCHK(out != NULL);
207 _ARGCHK(outlen != NULL);
208 _ARGCHK(key != NULL);
210 /* is this a private key? */
211 if (key->type != PK_PRIVATE) {
212 return CRYPT_PK_NOT_PRIVATE;
215 /* is the IDX valid ? */
216 if (is_valid_idx(key->idx) != 1) {
217 return CRYPT_PK_INVALID_TYPE;
220 if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
224 /* make up a key and export the public copy */
225 if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
229 pubkeysize = (unsigned long)sizeof(epubkey);
230 if ((err = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
235 /* get the hash and load it as a bignum into 'b' */
236 /* init the bignums */
237 if (mp_init_multi(&b, &p, NULL) != MP_OKAY) {
241 if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 64) != MP_OKAY) { goto error; }
242 if (mp_read_unsigned_bin(&b, (unsigned char *)in, (int)inlen) != MP_OKAY) { goto error; }
244 /* find b = (m - x)/k */
245 if (mp_invmod(&pubkey.k, &p, &pubkey.k) != MP_OKAY) { goto error; } /* k = 1/k */
246 if (mp_submod(&b, &key->k, &p, &b) != MP_OKAY) { goto error; } /* b = m - x */
247 if (mp_mulmod(&b, &pubkey.k, &p, &b) != MP_OKAY) { goto error; } /* b = (m - x)/k */
250 rsize = (unsigned long)mp_unsigned_bin_size(&b);
251 if (rsize > (unsigned long)sizeof(er)) {
254 (void)mp_to_unsigned_bin(&b, er);
256 /* now lets check the outlen before we write */
257 if (*outlen < (12 + rsize + pubkeysize)) {
258 res = CRYPT_BUFFER_OVERFLOW;
265 /* size of public key */
266 STORE32L(pubkeysize, out+y);
269 /* copy the public key */
270 for (x = 0; x < pubkeysize; x++, y++) {
275 STORE32L(rsize, out+y);
279 for (x = 0; x < rsize; x++, y++) {
284 packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
293 mp_clear_multi(&b, &p, NULL);
296 zeromem(er, sizeof(er));
297 zeromem(epubkey, sizeof(epubkey));
302 /* verify that mG = (bA + Y)
304 * The signatures work by making up a fresh key "a" with a public key "A". Now we want to sign so the
305 * public key Y = xG can verify it.
307 * b = (m - x)/k, A is the public key embedded and Y is the users public key [who signed it]
308 * A = kG therefore bA == ((m-x)/k)kG == (m-x)G
310 * Adding Y = xG to the bA gives us (m-x)G + xG == mG
312 * The user given only xG, kG and b cannot determine k or x which means they can't find the private key.
315 int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
316 const unsigned char *hash, unsigned long inlen,
317 int *stat, ecc_key *key)
325 _ARGCHK(sig != NULL);
326 _ARGCHK(hash != NULL);
327 _ARGCHK(hash != NULL);
328 _ARGCHK(key != NULL);
330 /* default to invalid signature */
333 if (siglen < PACKET_SIZE+4+4) {
334 return CRYPT_INVALID_PACKET;
336 siglen -= PACKET_SIZE+4+4;
339 /* is the message format correct? */
340 if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
347 /* get size of public key */
350 return CRYPT_INVALID_PACKET;
356 /* load the public key */
357 if ((err = ecc_import((unsigned char*)sig+y, x, &pubkey)) != CRYPT_OK) {
362 /* load size of 'b' */
365 return CRYPT_INVALID_PACKET;
372 if (mp_init_multi(&b, &m, &p, &mu, NULL) != MP_OKAY) {
379 mp_clear_multi(&b, &m, &p, &mu, NULL);
385 if (mp_read_unsigned_bin(&b, (unsigned char *)sig+y, (int)x) != MP_OKAY) { goto error; }
388 /* get m in binary a bignum */
389 if (mp_read_unsigned_bin(&m, (unsigned char *)hash, (int)inlen) != MP_OKAY) { goto error; }
392 if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
394 /* calculate barrett stuff */
396 mp_lshd(&mu, 2 * USED(&p));
397 if (mp_div(&mu, &p, &mu, NULL) != MP_OKAY) {
403 if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p) != CRYPT_OK) { goto error; }
406 if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p, &mu) != CRYPT_OK) { goto error; }
409 if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 64) != MP_OKAY) { goto error; }
410 if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 64) != MP_OKAY) { goto error; }
411 if (ecc_mulmod(&m, mG, mG, &p) != CRYPT_OK) { goto error; }
413 /* compare mG to bA + Y */
414 if (mp_cmp(&mG->x, &pubkey.pubkey.x) == MP_EQ && mp_cmp(&mG->y, &pubkey.pubkey.y) == MP_EQ) {
418 /* clear up and return */
426 mp_clear_multi(&p, &m, &b, &mu, NULL);