der_encode_integer.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. /* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
  13. int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen)
  14. {
  15. unsigned long tmplen, x, y, z;
  16. int err, leading_zero;
  17. _ARGCHK(num != NULL);
  18. _ARGCHK(out != NULL);
  19. _ARGCHK(outlen != NULL);
  20. /* find out how big this will be */
  21. if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
  22. return err;
  23. }
  24. if (*outlen < tmplen) {
  25. return CRYPT_BUFFER_OVERFLOW;
  26. }
  27. /* we only need a leading zero if the msb of the first byte is one */
  28. if ((mp_count_bits(num) & 7) == 7 || mp_iszero(num) == MP_YES) {
  29. leading_zero = 1;
  30. } else {
  31. leading_zero = 0;
  32. }
  33. /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
  34. y = mp_unsigned_bin_size(num) + leading_zero;
  35. /* now store initial data */
  36. *out++ = 0x02;
  37. if (y < 128) {
  38. /* short form */
  39. *out++ = (unsigned char)y;
  40. } else {
  41. /* long form (relies on y != 0) */
  42. /* get length of length... ;-) */
  43. x = y;
  44. z = 0;
  45. while (x) {
  46. ++z;
  47. x >>= 8;
  48. }
  49. /* store length of length */
  50. *out++ = 0x80 | ((unsigned char)z);
  51. /* now store length */
  52. /* first shift length up so msbyte != 0 */
  53. x = y;
  54. while ((x & 0xFF000000) == 0) {
  55. x <<= 8;
  56. }
  57. /* now store length */
  58. while (z--) {
  59. *out++ = (unsigned char)((x >> 24) & 0xFF);
  60. x <<= 8;
  61. }
  62. }
  63. /* now store msbyte of zero if num is non-zero */
  64. if (leading_zero) {
  65. *out++ = 0x00;
  66. }
  67. /* if it's not zero store it as big endian */
  68. if (mp_iszero(num) == MP_NO) {
  69. /* now store the mpint */
  70. if ((err = mp_to_unsigned_bin(num, out)) != MP_OKAY) {
  71. return mpi_to_ltc_error(err);
  72. }
  73. }
  74. /* we good */
  75. *outlen = tmplen;
  76. return CRYPT_OK;
  77. }