Mercurial > dropbear
comparison libtomcrypt/src/pk/ecc/ecc_sign_hash.c @ 1471:6dba84798cd5
Update to libtomcrypt 1.18.1, merged with Dropbear changes
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 09 Feb 2018 21:44:05 +0800 |
parents | f849a5ca2efc |
children | 8305ebe45940 |
comparison
equal
deleted
inserted
replaced
1470:8bba51a55704 | 1471:6dba84798cd5 |
---|---|
3 * LibTomCrypt is a library that provides various cryptographic | 3 * LibTomCrypt is a library that provides various cryptographic |
4 * algorithms in a highly modular and flexible manner. | 4 * algorithms in a highly modular and flexible manner. |
5 * | 5 * |
6 * The library is free for all purposes without any express | 6 * The library is free for all purposes without any express |
7 * guarantee it works. | 7 * guarantee it works. |
8 * | |
9 * Tom St Denis, [email protected], http://libtom.org | |
10 */ | 8 */ |
11 | 9 |
12 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b | |
13 * | |
14 * All curves taken from NIST recommendation paper of July 1999 | |
15 * Available at http://csrc.nist.gov/cryptval/dss.htm | |
16 */ | |
17 #include "tomcrypt.h" | 10 #include "tomcrypt.h" |
11 | |
12 #ifdef LTC_MECC | |
18 | 13 |
19 /** | 14 /** |
20 @file ecc_sign_hash.c | 15 @file ecc_sign_hash.c |
21 ECC Crypto, Tom St Denis | 16 ECC Crypto, Tom St Denis |
22 */ | 17 */ |
23 | 18 |
24 #if defined(LTC_MECC) && defined(LTC_DER) | 19 static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen, |
25 | |
26 /** | |
27 Sign a message digest | |
28 @param in The message digest to sign | |
29 @param inlen The length of the digest | |
30 @param out [out] The destination for the signature | |
31 @param outlen [in/out] The max size and resulting size of the signature | |
32 @param prng An active PRNG state | |
33 @param wprng The index of the PRNG you wish to use | |
34 @param key A private ECC key | |
35 @return CRYPT_OK if successful | |
36 */ | |
37 int ecc_sign_hash(const unsigned char *in, unsigned long inlen, | |
38 unsigned char *out, unsigned long *outlen, | 20 unsigned char *out, unsigned long *outlen, |
39 prng_state *prng, int wprng, ecc_key *key) | 21 prng_state *prng, int wprng, ecc_key *key, int sigformat) |
40 { | 22 { |
41 ecc_key pubkey; | 23 ecc_key pubkey; |
42 void *r, *s, *e, *p; | 24 void *r, *s, *e, *p; |
43 int err; | 25 int err, max_iterations = LTC_PK_MAX_RETRIES; |
26 unsigned long pbits, pbytes, i, shift_right; | |
27 unsigned char ch, buf[MAXBLOCKSIZE]; | |
44 | 28 |
45 LTC_ARGCHK(in != NULL); | 29 LTC_ARGCHK(in != NULL); |
46 LTC_ARGCHK(out != NULL); | 30 LTC_ARGCHK(out != NULL); |
47 LTC_ARGCHK(outlen != NULL); | 31 LTC_ARGCHK(outlen != NULL); |
48 LTC_ARGCHK(key != NULL); | 32 LTC_ARGCHK(key != NULL); |
59 | 43 |
60 if ((err = prng_is_valid(wprng)) != CRYPT_OK) { | 44 if ((err = prng_is_valid(wprng)) != CRYPT_OK) { |
61 return err; | 45 return err; |
62 } | 46 } |
63 | 47 |
64 /* get the hash and load it as a bignum into 'e' */ | |
65 /* init the bignums */ | 48 /* init the bignums */ |
66 if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) { | 49 if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) { |
67 return err; | 50 return err; |
68 } | 51 } |
69 if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; } | 52 if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; } |
70 if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto errnokey; } | 53 |
54 /* get the hash and load it as a bignum into 'e' */ | |
55 pbits = mp_count_bits(p); | |
56 pbytes = (pbits+7) >> 3; | |
57 if (pbits > inlen*8) { | |
58 if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } | |
59 } | |
60 else if (pbits % 8 == 0) { | |
61 if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } | |
62 } | |
63 else { | |
64 shift_right = 8 - pbits % 8; | |
65 for (i=0, ch=0; i<pbytes; i++) { | |
66 buf[i] = ch; | |
67 ch = (in[i] << (8-shift_right)); | |
68 buf[i] = buf[i] ^ (in[i] >> shift_right); | |
69 } | |
70 if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } | |
71 } | |
71 | 72 |
72 /* make up a key and export the public copy */ | 73 /* make up a key and export the public copy */ |
73 for (;;) { | 74 do { |
74 if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) { | 75 if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) { |
75 goto errnokey; | 76 goto errnokey; |
76 } | 77 } |
77 | 78 |
78 /* find r = x1 mod n */ | 79 /* find r = x1 mod n */ |
90 ecc_free(&pubkey); | 91 ecc_free(&pubkey); |
91 if (mp_iszero(s) == LTC_MP_NO) { | 92 if (mp_iszero(s) == LTC_MP_NO) { |
92 break; | 93 break; |
93 } | 94 } |
94 } | 95 } |
96 } while (--max_iterations > 0); | |
97 | |
98 if (max_iterations == 0) { | |
99 goto errnokey; | |
95 } | 100 } |
96 | 101 |
97 /* store as SEQUENCE { r, s -- integer } */ | 102 if (sigformat == 1) { |
103 /* RFC7518 format */ | |
104 if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; } | |
105 zeromem(out, 2*pbytes); | |
106 i = mp_unsigned_bin_size(r); | |
107 if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) { goto errnokey; } | |
108 i = mp_unsigned_bin_size(s); | |
109 if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) { goto errnokey; } | |
110 *outlen = 2*pbytes; | |
111 err = CRYPT_OK; | |
112 } | |
113 else { | |
114 /* store as ASN.1 SEQUENCE { r, s -- integer } */ | |
98 err = der_encode_sequence_multi(out, outlen, | 115 err = der_encode_sequence_multi(out, outlen, |
99 LTC_ASN1_INTEGER, 1UL, r, | 116 LTC_ASN1_INTEGER, 1UL, r, |
100 LTC_ASN1_INTEGER, 1UL, s, | 117 LTC_ASN1_INTEGER, 1UL, s, |
101 LTC_ASN1_EOL, 0UL, NULL); | 118 LTC_ASN1_EOL, 0UL, NULL); |
119 } | |
102 goto errnokey; | 120 goto errnokey; |
103 error: | 121 error: |
104 ecc_free(&pubkey); | 122 ecc_free(&pubkey); |
105 errnokey: | 123 errnokey: |
106 mp_clear_multi(r, s, p, e, NULL); | 124 mp_clear_multi(r, s, p, e, NULL); |
107 return err; | 125 return err; |
108 } | 126 } |
109 | 127 |
128 /** | |
129 Sign a message digest | |
130 @param in The message digest to sign | |
131 @param inlen The length of the digest | |
132 @param out [out] The destination for the signature | |
133 @param outlen [in/out] The max size and resulting size of the signature | |
134 @param prng An active PRNG state | |
135 @param wprng The index of the PRNG you wish to use | |
136 @param key A private ECC key | |
137 @return CRYPT_OK if successful | |
138 */ | |
139 int ecc_sign_hash(const unsigned char *in, unsigned long inlen, | |
140 unsigned char *out, unsigned long *outlen, | |
141 prng_state *prng, int wprng, ecc_key *key) | |
142 { | |
143 return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 0); | |
144 } | |
145 | |
146 /** | |
147 Sign a message digest in RFC7518 format | |
148 @param in The message digest to sign | |
149 @param inlen The length of the digest | |
150 @param out [out] The destination for the signature | |
151 @param outlen [in/out] The max size and resulting size of the signature | |
152 @param prng An active PRNG state | |
153 @param wprng The index of the PRNG you wish to use | |
154 @param key A private ECC key | |
155 @return CRYPT_OK if successful | |
156 */ | |
157 int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, | |
158 unsigned char *out, unsigned long *outlen, | |
159 prng_state *prng, int wprng, ecc_key *key) | |
160 { | |
161 return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 1); | |
162 } | |
163 | |
110 #endif | 164 #endif |
111 /* $Source$ */ | |
112 /* $Revision$ */ | |
113 /* $Date$ */ | |
114 | 165 |
166 /* ref: $Format:%D$ */ | |
167 /* git commit: $Format:%H$ */ | |
168 /* commit time: $Format:%ai$ */ |