pkcs_1_oaep_encode.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. /* OAEP Padding for PKCS #1 -- Tom St Denis */
  13. #ifdef PKCS_1
  14. int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen,
  15. const unsigned char *lparam, unsigned long lparamlen,
  16. unsigned long modulus_bitlen, prng_state *prng,
  17. int prng_idx, int hash_idx,
  18. unsigned char *out, unsigned long *outlen)
  19. {
  20. unsigned char *DB, *seed, *mask;
  21. unsigned long hLen, x, y, modulus_len;
  22. int err;
  23. _ARGCHK(msg != NULL);
  24. _ARGCHK(out != NULL);
  25. _ARGCHK(outlen != NULL);
  26. /* test valid hash */
  27. if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
  28. return err;
  29. }
  30. /* valid prng */
  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 of size modulus_len */
  37. DB = XMALLOC(modulus_len);
  38. mask = XMALLOC(modulus_len);
  39. seed = XMALLOC(modulus_len);
  40. if (DB == NULL || mask == NULL || seed == NULL) {
  41. if (DB != NULL) {
  42. XFREE(DB);
  43. }
  44. if (mask != NULL) {
  45. XFREE(mask);
  46. }
  47. if (seed != NULL) {
  48. XFREE(seed);
  49. }
  50. return CRYPT_MEM;
  51. }
  52. /* test message size */
  53. if (msglen > (modulus_len - 2*hLen - 2)) {
  54. err = CRYPT_PK_INVALID_SIZE;
  55. goto __ERR;
  56. }
  57. /* get lhash */
  58. /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
  59. x = modulus_len;
  60. if (lparam != NULL) {
  61. if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
  62. goto __ERR;
  63. }
  64. } else {
  65. /* can't pass hash_memory a NULL so use DB with zero length */
  66. if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
  67. goto __ERR;
  68. }
  69. }
  70. /* append PS then 0x01 (to lhash) */
  71. x = hLen;
  72. y = modulus_len - msglen - 2*hLen - 2;
  73. while (y--) {
  74. DB[x++] = 0x00;
  75. }
  76. DB[x++] = 0x01;
  77. /* message */
  78. y = msglen;
  79. while (y--) {
  80. DB[x++] = *msg++;
  81. }
  82. /* now choose a random seed */
  83. if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) {
  84. err = CRYPT_ERROR_READPRNG;
  85. goto __ERR;
  86. }
  87. /* compute MGF1 of seed (k - hlen - 1) */
  88. if ((err = pkcs_1_mgf1(seed, hLen, hash_idx, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
  89. goto __ERR;
  90. }
  91. /* xor against DB */
  92. for (y = 0; y < (modulus_len - hLen - 1); y++) {
  93. DB[y] ^= mask[y];
  94. }
  95. /* compute MGF1 of maskedDB (hLen) */
  96. if ((err = pkcs_1_mgf1(DB, modulus_len - hLen - 1, hash_idx, mask, hLen)) != CRYPT_OK) {
  97. goto __ERR;
  98. }
  99. /* XOR against seed */
  100. for (y = 0; y < hLen; y++) {
  101. seed[y] ^= mask[y];
  102. }
  103. /* create string of length modulus_len */
  104. if (*outlen < modulus_len) {
  105. err = CRYPT_BUFFER_OVERFLOW;
  106. goto __ERR;
  107. }
  108. /* start output which is 0x00 || maskedSeed || maskedDB */
  109. x = 0;
  110. out[x++] = 0x00;
  111. for (y = 0; y < hLen; y++) {
  112. out[x++] = seed[y];
  113. }
  114. for (y = 0; y < modulus_len - hLen - 1; y++) {
  115. out[x++] = DB[y];
  116. }
  117. *outlen = x;
  118. err = CRYPT_OK;
  119. __ERR:
  120. #ifdef CLEAN_STACK
  121. zeromem(DB, modulus_len);
  122. zeromem(seed, modulus_len);
  123. zeromem(mask, modulus_len);
  124. #endif
  125. XFREE(seed);
  126. XFREE(mask);
  127. XFREE(DB);
  128. return err;
  129. }
  130. #endif /* PKCS_1 */