sshbuf-getput-crypto.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* $OpenBSD: sshbuf-getput-crypto.c,v 1.8 2019/11/15 06:00:20 djm Exp $ */
  2. /*
  3. * Copyright (c) 2011 Damien Miller
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. #define SSHBUF_INTERNAL
  18. #include "includes.h"
  19. #include <sys/types.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #ifdef WITH_OPENSSL
  24. #include <openssl/bn.h>
  25. #ifdef OPENSSL_HAS_ECC
  26. # include <openssl/ec.h>
  27. #endif /* OPENSSL_HAS_ECC */
  28. #include "ssherr.h"
  29. #include "sshbuf.h"
  30. int
  31. sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp)
  32. {
  33. BIGNUM *v;
  34. const u_char *d;
  35. size_t len;
  36. int r;
  37. if (valp != NULL)
  38. *valp = NULL;
  39. if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
  40. return r;
  41. if (valp != NULL) {
  42. if ((v = BN_new()) == NULL ||
  43. BN_bin2bn(d, len, v) == NULL) {
  44. BN_clear_free(v);
  45. return SSH_ERR_ALLOC_FAIL;
  46. }
  47. *valp = v;
  48. }
  49. return 0;
  50. }
  51. #ifdef OPENSSL_HAS_ECC
  52. static int
  53. get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
  54. {
  55. /* Refuse overlong bignums */
  56. if (len == 0 || len > SSHBUF_MAX_ECPOINT)
  57. return SSH_ERR_ECPOINT_TOO_LARGE;
  58. /* Only handle uncompressed points */
  59. if (*d != POINT_CONVERSION_UNCOMPRESSED)
  60. return SSH_ERR_INVALID_FORMAT;
  61. if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
  62. return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
  63. return 0;
  64. }
  65. int
  66. sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
  67. {
  68. const u_char *d;
  69. size_t len;
  70. int r;
  71. if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
  72. return r;
  73. if ((r = get_ec(d, len, v, g)) != 0)
  74. return r;
  75. /* Skip string */
  76. if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
  77. /* Shouldn't happen */
  78. SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
  79. SSHBUF_ABORT();
  80. return SSH_ERR_INTERNAL_ERROR;
  81. }
  82. return 0;
  83. }
  84. int
  85. sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
  86. {
  87. EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
  88. int r;
  89. const u_char *d;
  90. size_t len;
  91. if (pt == NULL) {
  92. SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
  93. return SSH_ERR_ALLOC_FAIL;
  94. }
  95. if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
  96. EC_POINT_free(pt);
  97. return r;
  98. }
  99. if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
  100. EC_POINT_free(pt);
  101. return r;
  102. }
  103. if (EC_KEY_set_public_key(v, pt) != 1) {
  104. EC_POINT_free(pt);
  105. return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
  106. }
  107. EC_POINT_free(pt);
  108. /* Skip string */
  109. if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
  110. /* Shouldn't happen */
  111. SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
  112. SSHBUF_ABORT();
  113. return SSH_ERR_INTERNAL_ERROR;
  114. }
  115. return 0;
  116. }
  117. #endif /* OPENSSL_HAS_ECC */
  118. int
  119. sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
  120. {
  121. u_char d[SSHBUF_MAX_BIGNUM + 1];
  122. int len = BN_num_bytes(v), prepend = 0, r;
  123. if (len < 0 || len > SSHBUF_MAX_BIGNUM)
  124. return SSH_ERR_INVALID_ARGUMENT;
  125. *d = '\0';
  126. if (BN_bn2bin(v, d + 1) != len)
  127. return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
  128. /* If MSB is set, prepend a \0 */
  129. if (len > 0 && (d[1] & 0x80) != 0)
  130. prepend = 1;
  131. if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
  132. explicit_bzero(d, sizeof(d));
  133. return r;
  134. }
  135. explicit_bzero(d, sizeof(d));
  136. return 0;
  137. }
  138. #ifdef OPENSSL_HAS_ECC
  139. int
  140. sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
  141. {
  142. u_char d[SSHBUF_MAX_ECPOINT];
  143. size_t len;
  144. int ret;
  145. if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
  146. NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) {
  147. return SSH_ERR_INVALID_ARGUMENT;
  148. }
  149. if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
  150. d, len, NULL) != len) {
  151. return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
  152. }
  153. ret = sshbuf_put_string(buf, d, len);
  154. explicit_bzero(d, len);
  155. return ret;
  156. }
  157. int
  158. sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
  159. {
  160. return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
  161. EC_KEY_get0_group(v));
  162. }
  163. #endif /* OPENSSL_HAS_ECC */
  164. #endif /* WITH_OPENSSL */