2
0

pkcs_1_pss_encode.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. /* PKCS #1 PSS Signature Padding -- Tom St Denis */
  13. #ifdef PKCS_1
  14. int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen,
  15. unsigned long saltlen, prng_state *prng,
  16. int prng_idx, int hash_idx,
  17. unsigned long modulus_bitlen,
  18. unsigned char *out, unsigned long *outlen)
  19. {
  20. unsigned char *DB, *mask, *salt, *hash;
  21. unsigned long x, y, hLen, modulus_len;
  22. int err;
  23. hash_state md;
  24. _ARGCHK(msghash != NULL);
  25. _ARGCHK(out != NULL);
  26. _ARGCHK(outlen != NULL);
  27. /* ensure hash and PRNG are valid */
  28. if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
  29. return err;
  30. }
  31. if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
  32. return err;
  33. }
  34. hLen = hash_descriptor[hash_idx].hashsize;
  35. modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0);
  36. /* allocate ram for DB/mask/salt/hash of size modulus_len */
  37. DB = XMALLOC(modulus_len);
  38. mask = XMALLOC(modulus_len);
  39. salt = XMALLOC(modulus_len);
  40. hash = XMALLOC(modulus_len);
  41. if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) {
  42. if (DB != NULL) {
  43. XFREE(DB);
  44. }
  45. if (mask != NULL) {
  46. XFREE(mask);
  47. }
  48. if (salt != NULL) {
  49. XFREE(salt);
  50. }
  51. if (hash != NULL) {
  52. XFREE(hash);
  53. }
  54. return CRYPT_MEM;
  55. }
  56. /* check sizes */
  57. if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) {
  58. err = CRYPT_INVALID_ARG;
  59. goto __ERR;
  60. }
  61. /* generate random salt */
  62. if (saltlen > 0) {
  63. if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) {
  64. err = CRYPT_ERROR_READPRNG;
  65. goto __ERR;
  66. }
  67. }
  68. /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
  69. hash_descriptor[hash_idx].init(&md);
  70. zeromem(DB, 8);
  71. if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
  72. goto __ERR;
  73. }
  74. if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
  75. goto __ERR;
  76. }
  77. if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {
  78. goto __ERR;
  79. }
  80. if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {
  81. goto __ERR;
  82. }
  83. /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
  84. for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) {
  85. DB[x] = 0x00;
  86. }
  87. DB[x++] = 0x01;
  88. for (y = 0; y < saltlen; y++) {
  89. DB[x++] = salt[y];
  90. }
  91. /* generate mask of length modulus_len - hLen - 1 from hash */
  92. if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
  93. goto __ERR;
  94. }
  95. /* xor against DB */
  96. for (y = 0; y < (modulus_len - hLen - 1); y++) {
  97. DB[y] ^= mask[y];
  98. }
  99. /* output is DB || hash || 0xBC */
  100. if (*outlen < modulus_len) {
  101. err = CRYPT_BUFFER_OVERFLOW;
  102. goto __ERR;
  103. }
  104. /* DB */
  105. for (y = x = 0; x < modulus_len - hLen - 1; x++) {
  106. out[y++] = DB[x];
  107. }
  108. /* hash */
  109. for (x = 0; x < hLen; x++) {
  110. out[y++] = hash[x];
  111. }
  112. /* 0xBC */
  113. out[y] = 0xBC;
  114. /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
  115. out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
  116. /* store output size */
  117. *outlen = modulus_len;
  118. err = CRYPT_OK;
  119. __ERR:
  120. #ifdef CLEAN_STACK
  121. zeromem(DB, modulus_len);
  122. zeromem(mask, modulus_len);
  123. zeromem(salt, modulus_len);
  124. zeromem(hash, modulus_len);
  125. #endif
  126. XFREE(hash);
  127. XFREE(salt);
  128. XFREE(mask);
  129. XFREE(DB);
  130. return err;
  131. }
  132. #endif /* PKCS_1 */