Home | History | Annotate | Download | only in ecc
      1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
      2  *
      3  * LibTomCrypt is a library that provides various cryptographic
      4  * algorithms in a highly modular and flexible manner.
      5  *
      6  * The library is free for all purposes without any express
      7  * guarantee it works.
      8  *
      9  * Tom St Denis, tomstdenis (at) gmail.com, http://libtomcrypt.com
     10  */
     11 
     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"
     18 
     19 /**
     20   @file ecc_sign_hash.c
     21   ECC Crypto, Tom St Denis
     22 */
     23 
     24 #ifdef MECC
     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,
     39                         prng_state *prng, int wprng, ecc_key *key)
     40 {
     41    ecc_key       pubkey;
     42    void          *r, *s, *e, *p;
     43    int           err;
     44 
     45    LTC_ARGCHK(in     != NULL);
     46    LTC_ARGCHK(out    != NULL);
     47    LTC_ARGCHK(outlen != NULL);
     48    LTC_ARGCHK(key    != NULL);
     49 
     50    /* is this a private key? */
     51    if (key->type != PK_PRIVATE) {
     52       return CRYPT_PK_NOT_PRIVATE;
     53    }
     54 
     55    /* is the IDX valid ?  */
     56    if (ltc_ecc_is_valid_idx(key->idx) != 1) {
     57       return CRYPT_PK_INVALID_TYPE;
     58    }
     59 
     60    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
     61       return err;
     62    }
     63 
     64    /* get the hash and load it as a bignum into 'e' */
     65    /* init the bignums */
     66    if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {
     67       return err;
     68    }
     69    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; }
     71 
     72    /* make up a key and export the public copy */
     73    for (;;) {
     74       if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
     75          goto errnokey;
     76       }
     77 
     78       /* find r = x1 mod n */
     79       if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK)                 { goto error; }
     80 
     81       if (mp_iszero(r) == LTC_MP_YES) {
     82          ecc_free(&pubkey);
     83       } else {
     84         /* find s = (e + xr)/k */
     85         if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK)            { goto error; } /* k = 1/k */
     86         if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK)                  { goto error; } /* s = xr */
     87         if ((err = mp_add(e, s, s)) != CRYPT_OK)                             { goto error; } /* s = e +  xr */
     88         if ((err = mp_mod(s, p, s)) != CRYPT_OK)                             { goto error; } /* s = e +  xr */
     89         if ((err = mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK)                { goto error; } /* s = (e + xr)/k */
     90         ecc_free(&pubkey);
     91         if (mp_iszero(s) == LTC_MP_NO) {
     92            break;
     93         }
     94       }
     95    }
     96 
     97    /* store as SEQUENCE { r, s -- integer } */
     98    err = der_encode_sequence_multi(out, outlen,
     99                              LTC_ASN1_INTEGER, 1UL, r,
    100                              LTC_ASN1_INTEGER, 1UL, s,
    101                              LTC_ASN1_EOL, 0UL, NULL);
    102    goto errnokey;
    103 error:
    104    ecc_free(&pubkey);
    105 errnokey:
    106    mp_clear_multi(r, s, p, e, NULL);
    107    return err;
    108 }
    109 
    110 #endif
    111 /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_sign_hash.c,v $ */
    112 /* $Revision: 1.9 $ */
    113 /* $Date: 2006/12/04 02:50:11 $ */
    114 
    115