dsa_sign_hash.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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, [email protected], http://libtomcrypt.org
  10. */
  11. #include "mycrypt.h"
  12. #ifdef MDSA
  13. int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
  14. unsigned char *out, unsigned long *outlen,
  15. prng_state *prng, int wprng, dsa_key *key)
  16. {
  17. mp_int k, kinv, tmp, r, s;
  18. unsigned char *buf;
  19. int err, y;
  20. unsigned long len;
  21. _ARGCHK(in != NULL);
  22. _ARGCHK(out != NULL);
  23. _ARGCHK(outlen != NULL);
  24. _ARGCHK(key != NULL);
  25. if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
  26. return err;
  27. }
  28. if (key->type != PK_PRIVATE) {
  29. return CRYPT_PK_NOT_PRIVATE;
  30. }
  31. /* check group order size */
  32. if (key->qord >= MDSA_MAX_GROUP) {
  33. return CRYPT_INVALID_ARG;
  34. }
  35. buf = XMALLOC(MDSA_MAX_GROUP);
  36. if (buf == NULL) {
  37. return CRYPT_MEM;
  38. }
  39. /* Init our temps */
  40. if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY) { goto error; }
  41. retry:
  42. do {
  43. /* gen random k */
  44. if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
  45. err = CRYPT_ERROR_READPRNG;
  46. goto __ERR;
  47. }
  48. /* read k */
  49. if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; }
  50. /* k > 1 ? */
  51. if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; }
  52. /* test gcd */
  53. if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; }
  54. } while (mp_cmp_d(&tmp, 1) != MP_EQ);
  55. /* now find 1/k mod q */
  56. if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; }
  57. /* now find r = g^k mod p mod q */
  58. if ((err = mp_exptmod(&key->g, &k, &key->p, &r)) != MP_OKAY) { goto error; }
  59. if ((err = mp_mod(&r, &key->q, &r)) != MP_OKAY) { goto error; }
  60. if (mp_iszero(&r) == MP_YES) { goto retry; }
  61. /* now find s = (in + xr)/k mod q */
  62. if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
  63. if ((err = mp_mul(&key->x, &r, &s)) != MP_OKAY) { goto error; }
  64. if ((err = mp_add(&s, &tmp, &s)) != MP_OKAY) { goto error; }
  65. if ((err = mp_mulmod(&s, &kinv, &key->q, &s)) != MP_OKAY) { goto error; }
  66. if (mp_iszero(&s) == MP_YES) { goto retry; }
  67. /* now store em both */
  68. /* first check that we have enough room */
  69. if (*outlen < (unsigned long)(PACKET_SIZE + 4 + mp_unsigned_bin_size(&s) + mp_unsigned_bin_size(&r))) {
  70. err = CRYPT_BUFFER_OVERFLOW;
  71. goto __ERR;
  72. }
  73. /* packet header */
  74. packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_SIGNED);
  75. y = PACKET_SIZE;
  76. /* store length of r */
  77. len = mp_unsigned_bin_size(&r);
  78. out[y++] = (len>>8)&255;
  79. out[y++] = len&255;
  80. /* store r */
  81. if ((err = mp_to_unsigned_bin(&r, out+y)) != MP_OKAY) { goto error; }
  82. y += len;
  83. /* store length of s */
  84. len = mp_unsigned_bin_size(&s);
  85. out[y++] = (len>>8)&255;
  86. out[y++] = len&255;
  87. /* store s */
  88. if ((err = mp_to_unsigned_bin(&s, out+y)) != MP_OKAY) { goto error; }
  89. y += len;
  90. /* reset size */
  91. *outlen = y;
  92. err = CRYPT_OK;
  93. goto __ERR;
  94. error:
  95. err = mpi_to_ltc_error(err);
  96. __ERR:
  97. mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL);
  98. #ifdef CLEAN_STACK
  99. zeromem(buf, MDSA_MAX_GROUP);
  100. #endif
  101. XFREE(buf);
  102. return err;
  103. }
  104. #endif