pkcs_1_pss_encode.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) {
  70. goto __ERR;
  71. }
  72. zeromem(DB, 8);
  73. if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) {
  74. goto __ERR;
  75. }
  76. if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) {
  77. goto __ERR;
  78. }
  79. if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) {
  80. goto __ERR;
  81. }
  82. if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) {
  83. goto __ERR;
  84. }
  85. /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */
  86. for (x = 0; x < (modulus_len - saltlen - hLen - 2); x++) {
  87. DB[x] = 0x00;
  88. }
  89. DB[x++] = 0x01;
  90. for (y = 0; y < saltlen; y++) {
  91. DB[x++] = salt[y];
  92. }
  93. /* generate mask of length modulus_len - hLen - 1 from hash */
  94. if ((err = pkcs_1_mgf1(hash, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
  95. goto __ERR;
  96. }
  97. /* xor against DB */
  98. for (y = 0; y < (modulus_len - hLen - 1); y++) {
  99. DB[y] ^= mask[y];
  100. }
  101. /* output is DB || hash || 0xBC */
  102. if (*outlen < modulus_len) {
  103. err = CRYPT_BUFFER_OVERFLOW;
  104. goto __ERR;
  105. }
  106. /* DB */
  107. for (y = x = 0; x < modulus_len - hLen - 1; x++) {
  108. out[y++] = DB[x];
  109. }
  110. /* hash */
  111. for (x = 0; x < hLen; x++) {
  112. out[y++] = hash[x];
  113. }
  114. /* 0xBC */
  115. out[y] = 0xBC;
  116. /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
  117. out[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen-1));
  118. /* store output size */
  119. *outlen = modulus_len;
  120. err = CRYPT_OK;
  121. __ERR:
  122. #ifdef CLEAN_STACK
  123. zeromem(DB, modulus_len);
  124. zeromem(mask, modulus_len);
  125. zeromem(salt, modulus_len);
  126. zeromem(hash, modulus_len);
  127. #endif
  128. XFREE(hash);
  129. XFREE(salt);
  130. XFREE(mask);
  131. XFREE(DB);
  132. return err;
  133. }
  134. #endif /* PKCS_1 */