77 * guarantee it works.
88 */
99
10- /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
11- *
12- * All curves taken from NIST recommendation paper of July 1999
13- * Available at http://csrc.nist.gov/cryptval/dss.htm
14- */
1510#include "tomcrypt.h"
1611
12+ #ifdef LTC_MECC
13+
1714/**
1815 @file ecc_sign_hash.c
1916 ECC Crypto, Tom St Denis
2017*/
2118
22- #ifdef LTC_MECC
23-
24- /**
25- Sign a hash with ECC
26- @param in The hash to sign
27- @param inlen The length of the hash to sign
28- @param r The "r" integer of the signature (caller must initialize with mp_init() first)
29- @param s The "s" integer of the signature (caller must initialize with mp_init() first)
30- @param prng An active PRNG state
31- @param wprng The index of the PRNG desired
32- @param key A private ECC key
33- @return CRYPT_OK if successful
34- */
35- int ecc_sign_hash_raw (const unsigned char * in , unsigned long inlen ,
36- void * r , void * s ,
37- prng_state * prng , int wprng , ecc_key * key )
19+ static int _ecc_sign_hash (const unsigned char * in , unsigned long inlen ,
20+ unsigned char * out , unsigned long * outlen ,
21+ prng_state * prng , int wprng , ecc_key * key , int sigformat )
3822{
3923 ecc_key pubkey ;
40- void * e , * p ;
41- int err ;
24+ void * r , * s , * e , * p ;
25+ int err , max_iterations = PK_MAX_RETRIES ;
26+ unsigned long pbits , pbytes , i , shift_right ;
27+ unsigned char ch , buf [MAXBLOCKSIZE ];
4228
43- LTC_ARGCHK (in != NULL );
44- LTC_ARGCHK (r != NULL );
45- LTC_ARGCHK (s != NULL );
46- LTC_ARGCHK (key != NULL );
29+ LTC_ARGCHK (in != NULL );
30+ LTC_ARGCHK (out != NULL );
31+ LTC_ARGCHK (outlen != NULL );
32+ LTC_ARGCHK (key != NULL );
4733
4834 /* is this a private key? */
4935 if (key -> type != PK_PRIVATE ) {
@@ -59,46 +45,83 @@ int ecc_sign_hash_raw(const unsigned char *in, unsigned long inlen,
5945 return err ;
6046 }
6147
62- /* get the hash and load it as a bignum into 'e' */
6348 /* init the bignums */
64- if ((err = mp_init_multi (& p , & e , NULL )) != CRYPT_OK ) {
49+ if ((err = mp_init_multi (& r , & s , & p , & e , NULL )) != CRYPT_OK ) {
6550 return err ;
6651 }
67- if ((err = mp_read_radix (p , (char * )key -> dp -> order , 16 )) != CRYPT_OK ) { goto errnokey ; }
68- if ((err = mp_read_unsigned_bin (e , (unsigned char * )in , (int )inlen )) != CRYPT_OK ) { goto errnokey ; }
52+ if ((err = mp_read_radix (p , (char * )key -> dp -> order , 16 )) != 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+ }
6972
7073 /* make up a key and export the public copy */
71- for (;;) {
74+ do {
7275 if ((err = ecc_make_key_ex (prng , wprng , & pubkey , key -> dp )) != CRYPT_OK ) {
7376 goto errnokey ;
7477 }
7578
7679 /* find r = x1 mod n */
77- if ((err = mp_mod (pubkey .pubkey .x , p , r )) != CRYPT_OK ) { goto error ; }
80+ if ((err = mp_mod (pubkey .pubkey .x , p , r )) != CRYPT_OK ) { goto error ; }
7881
7982 if (mp_iszero (r ) == LTC_MP_YES ) {
8083 ecc_free (& pubkey );
8184 } else {
82- /* find s = (e + xr)/k */
83- if ((err = mp_invmod (pubkey .k , p , pubkey .k )) != CRYPT_OK ) { goto error ; } /* k = 1/k */
84- if ((err = mp_mulmod (key -> k , r , p , s )) != CRYPT_OK ) { goto error ; } /* s = xr */
85- if ((err = mp_add (e , s , s )) != CRYPT_OK ) { goto error ; } /* s = e + xr */
86- if ((err = mp_mod (s , p , s )) != CRYPT_OK ) { goto error ; } /* s = e + xr */
87- if ((err = mp_mulmod (s , pubkey .k , p , s )) != CRYPT_OK ) { goto error ; } /* s = (e + xr)/k */
88- ecc_free (& pubkey );
89- if (mp_iszero (s ) == LTC_MP_NO ) {
90- break ;
91- }
85+ /* find s = (e + xr)/k */
86+ if ((err = mp_invmod (pubkey .k , p , pubkey .k )) != CRYPT_OK ) { goto error ; } /* k = 1/k */
87+ if ((err = mp_mulmod (key -> k , r , p , s )) != CRYPT_OK ) { goto error ; } /* s = xr */
88+ if ((err = mp_add (e , s , s )) != CRYPT_OK ) { goto error ; } /* s = e + xr */
89+ if ((err = mp_mod (s , p , s )) != CRYPT_OK ) { goto error ; } /* s = e + xr */
90+ if ((err = mp_mulmod (s , pubkey .k , p , s )) != CRYPT_OK ) { goto error ; } /* s = (e + xr)/k */
91+ ecc_free (& pubkey );
92+ if (mp_iszero (s ) == LTC_MP_NO ) {
93+ break ;
94+ }
9295 }
96+ } while (-- max_iterations > 0 );
97+
98+ if (max_iterations == 0 ) {
99+ goto errnokey ;
93100 }
94101
95- err = CRYPT_OK ;
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 } */
115+ err = der_encode_sequence_multi (out , outlen ,
116+ LTC_ASN1_INTEGER , 1UL , r ,
117+ LTC_ASN1_INTEGER , 1UL , s ,
118+ LTC_ASN1_EOL , 0UL , NULL );
119+ }
96120 goto errnokey ;
97-
98121error :
99122 ecc_free (& pubkey );
100123errnokey :
101- mp_clear_multi (p , e , NULL );
124+ mp_clear_multi (r , s , p , e , NULL );
102125 return err ;
103126}
104127
@@ -117,35 +140,29 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
117140 unsigned char * out , unsigned long * outlen ,
118141 prng_state * prng , int wprng , ecc_key * key )
119142{
120- void * r , * s ;
121- int err ;
122-
123- LTC_ARGCHK (in != NULL );
124- LTC_ARGCHK (out != NULL );
125- LTC_ARGCHK (outlen != NULL );
126- LTC_ARGCHK (key != NULL );
127-
128- if (mp_init_multi (& r , & s , NULL ) != CRYPT_OK ) {
129- return CRYPT_MEM ;
130- }
131-
132- if ((err = ecc_sign_hash_raw (in , inlen , r , s , prng , wprng , key )) != CRYPT_OK ) {
133- goto error ;
134- }
135-
136- /* store as SEQUENCE { r, s -- integer } */
137- err = der_encode_sequence_multi (out , outlen ,
138- LTC_ASN1_INTEGER , 1UL , r ,
139- LTC_ASN1_INTEGER , 1UL , s ,
140- LTC_ASN1_EOL , 0UL , NULL );
143+ return _ecc_sign_hash (in , inlen , out , outlen , prng , wprng , key , 0 );
144+ }
141145
142- error :
143- mp_clear_multi (r , s , NULL );
144- return err ;
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 );
145162}
146163
147164#endif
165+
148166/* ref: $Format:%D$ */
149167/* git commit: $Format:%H$ */
150168/* commit time: $Format:%ai$ */
151-
0 commit comments