tls_rsa.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * Copyright (C) 2017 Denys Vlasenko
  3. *
  4. * Licensed under GPLv2, see file LICENSE in this source tree.
  5. */
  6. #include "tls.h"
  7. /* The code below is taken from parts of
  8. * matrixssl-3-7-2b-open/crypto/pubkey/pkcs.c
  9. * matrixssl-3-7-2b-open/crypto/pubkey/rsa.c
  10. * and (so far) almost not modified. Changes are flagged with //bbox
  11. */
  12. #define pkcs1Pad(in, inlen, out, outlen, cryptType, userPtr) \
  13. pkcs1Pad(in, inlen, out, outlen, cryptType)
  14. static //bbox
  15. int32 pkcs1Pad(unsigned char *in, uint32 inlen, unsigned char *out,
  16. uint32 outlen, int32 cryptType, void *userPtr)
  17. {
  18. unsigned char *c;
  19. int32 randomLen;
  20. randomLen = outlen - 3 - inlen;
  21. if (randomLen < 8) {
  22. psTraceCrypto("pkcs1Pad failure\n");
  23. return PS_LIMIT_FAIL;
  24. }
  25. c = out;
  26. *c = 0x00;
  27. c++;
  28. *c = (unsigned char)cryptType;
  29. c++;
  30. if (cryptType == PUBKEY_TYPE) {
  31. while (randomLen-- > 0) {
  32. *c++ = 0xFF;
  33. }
  34. } else {
  35. if (matrixCryptoGetPrngData(c, (uint32)randomLen, userPtr) < 0) {
  36. return PS_PLATFORM_FAIL;
  37. }
  38. /*
  39. SECURITY: Read through the random data and change all 0x0 to 0x01.
  40. This is per spec that no random bytes should be 0
  41. */
  42. while (randomLen-- > 0) {
  43. if (*c == 0x0) {
  44. *c = 0x01;
  45. }
  46. c++;
  47. }
  48. }
  49. *c = 0x00;
  50. c++;
  51. memcpy(c, in, inlen);
  52. return outlen;
  53. }
  54. #define psRsaCrypt(pool, in, inlen, out, outlen, key, type, data) \
  55. psRsaCrypt( in, inlen, out, outlen, key, type)
  56. static //bbox
  57. int32 psRsaCrypt(psPool_t *pool, const unsigned char *in, uint32 inlen,
  58. unsigned char *out, uint32 *outlen, psRsaKey_t *key, int32 type,
  59. void *data)
  60. {
  61. pstm_int tmp, tmpa, tmpb;
  62. int32 res;
  63. uint32 x;
  64. //bbox
  65. // if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
  66. // psTraceCrypto("NULL parameter error in psRsaCrypt\n");
  67. // return PS_ARG_FAIL;
  68. // }
  69. tmp.dp = tmpa.dp = tmpb.dp = NULL;
  70. /* Init and copy into tmp */
  71. if (pstm_init_for_read_unsigned_bin(pool, &tmp, inlen + sizeof(pstm_digit))
  72. != PS_SUCCESS) {
  73. return PS_FAILURE;
  74. }
  75. if (pstm_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != PS_SUCCESS){
  76. pstm_clear(&tmp);
  77. return PS_FAILURE;
  78. }
  79. /* Sanity check on the input */
  80. if (pstm_cmp(&key->N, &tmp) == PSTM_LT) {
  81. res = PS_LIMIT_FAIL;
  82. goto done;
  83. }
  84. if (type == PRIVKEY_TYPE) {
  85. if (key->optimized) {
  86. if (pstm_init_size(pool, &tmpa, key->p.alloc) != PS_SUCCESS) {
  87. res = PS_FAILURE;
  88. goto done;
  89. }
  90. if (pstm_init_size(pool, &tmpb, key->q.alloc) != PS_SUCCESS) {
  91. pstm_clear(&tmpa);
  92. res = PS_FAILURE;
  93. goto done;
  94. }
  95. if (pstm_exptmod(pool, &tmp, &key->dP, &key->p, &tmpa) !=
  96. PS_SUCCESS) {
  97. psTraceCrypto("decrypt error: pstm_exptmod dP, p\n");
  98. goto error;
  99. }
  100. if (pstm_exptmod(pool, &tmp, &key->dQ, &key->q, &tmpb) !=
  101. PS_SUCCESS) {
  102. psTraceCrypto("decrypt error: pstm_exptmod dQ, q\n");
  103. goto error;
  104. }
  105. if (pstm_sub(&tmpa, &tmpb, &tmp) != PS_SUCCESS) {
  106. psTraceCrypto("decrypt error: sub tmpb, tmp\n");
  107. goto error;
  108. }
  109. if (pstm_mulmod(pool, &tmp, &key->qP, &key->p, &tmp) != PS_SUCCESS) {
  110. psTraceCrypto("decrypt error: pstm_mulmod qP, p\n");
  111. goto error;
  112. }
  113. if (pstm_mul_comba(pool, &tmp, &key->q, &tmp, NULL, 0)
  114. != PS_SUCCESS){
  115. psTraceCrypto("decrypt error: pstm_mul q \n");
  116. goto error;
  117. }
  118. if (pstm_add(&tmp, &tmpb, &tmp) != PS_SUCCESS) {
  119. psTraceCrypto("decrypt error: pstm_add tmp \n");
  120. goto error;
  121. }
  122. } else {
  123. if (pstm_exptmod(pool, &tmp, &key->d, &key->N, &tmp) !=
  124. PS_SUCCESS) {
  125. psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
  126. goto error;
  127. }
  128. }
  129. } else if (type == PUBKEY_TYPE) {
  130. if (pstm_exptmod(pool, &tmp, &key->e, &key->N, &tmp) != PS_SUCCESS) {
  131. psTraceCrypto("psRsaCrypt error: pstm_exptmod\n");
  132. goto error;
  133. }
  134. } else {
  135. psTraceCrypto("psRsaCrypt error: invalid type param\n");
  136. goto error;
  137. }
  138. /* Read it back */
  139. x = pstm_unsigned_bin_size(&key->N);
  140. if ((uint32)x > *outlen) {
  141. res = -1;
  142. psTraceCrypto("psRsaCrypt error: pstm_unsigned_bin_size\n");
  143. goto done;
  144. }
  145. /* We want the encrypted value to always be the key size. Pad with 0x0 */
  146. while ((uint32)x < (unsigned long)key->size) {
  147. *out++ = 0x0;
  148. x++;
  149. }
  150. *outlen = x;
  151. /* Convert it */
  152. memset(out, 0x0, x);
  153. if (pstm_to_unsigned_bin(pool, &tmp, out+(x-pstm_unsigned_bin_size(&tmp)))
  154. != PS_SUCCESS) {
  155. psTraceCrypto("psRsaCrypt error: pstm_to_unsigned_bin\n");
  156. goto error;
  157. }
  158. /* Clean up and return */
  159. res = PS_SUCCESS;
  160. goto done;
  161. error:
  162. res = PS_FAILURE;
  163. done:
  164. if (type == PRIVKEY_TYPE && key->optimized) {
  165. //pstm_clear_multi(&tmpa, &tmpb, NULL, NULL, NULL, NULL, NULL, NULL);
  166. pstm_clear(&tmpa);
  167. pstm_clear(&tmpb);
  168. }
  169. pstm_clear(&tmp);
  170. return res;
  171. }
  172. int32 FAST_FUNC psRsaEncryptPub(psPool_t *pool, psRsaKey_t *key,
  173. unsigned char *in, uint32 inlen,
  174. unsigned char *out, uint32 outlen, void *data)
  175. {
  176. int32 err;
  177. uint32 size;
  178. size = key->size;
  179. if (outlen < size) {
  180. //bbox psTraceCrypto("Error on bad outlen parameter to psRsaEncryptPub\n");
  181. bb_error_msg_and_die("RSA crypt outlen:%d < size:%d", outlen, size);
  182. return PS_ARG_FAIL;
  183. }
  184. if ((err = pkcs1Pad(in, inlen, out, size, PRIVKEY_TYPE, data))
  185. < PS_SUCCESS) {
  186. psTraceCrypto("Error padding psRsaEncryptPub. Likely data too long\n");
  187. return err;
  188. }
  189. if ((err = psRsaCrypt(pool, out, size, out, (uint32*)&outlen, key,
  190. PUBKEY_TYPE, data)) < PS_SUCCESS) {
  191. psTraceCrypto("Error performing psRsaEncryptPub\n");
  192. return err;
  193. }
  194. if (outlen != size) {
  195. psTraceCrypto("Encrypted size error in psRsaEncryptPub\n");
  196. return PS_FAILURE;
  197. }
  198. return size;
  199. }