digest-openssl.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* $OpenBSD: digest-openssl.c,v 1.7 2017/05/08 22:57:38 djm Exp $ */
  2. /*
  3. * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
  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. #include "includes.h"
  18. #ifdef WITH_OPENSSL
  19. #include <sys/types.h>
  20. #include <limits.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <openssl/evp.h>
  24. #include "openbsd-compat/openssl-compat.h"
  25. #include "sshbuf.h"
  26. #include "digest.h"
  27. #include "ssherr.h"
  28. #ifndef HAVE_EVP_SHA256
  29. # define EVP_sha256 NULL
  30. #endif
  31. #ifndef HAVE_EVP_SHA384
  32. # define EVP_sha384 NULL
  33. #endif
  34. #ifndef HAVE_EVP_SHA512
  35. # define EVP_sha512 NULL
  36. #endif
  37. struct ssh_digest_ctx {
  38. int alg;
  39. EVP_MD_CTX *mdctx;
  40. };
  41. struct ssh_digest {
  42. int id;
  43. const char *name;
  44. size_t digest_len;
  45. const EVP_MD *(*mdfunc)(void);
  46. };
  47. /* NB. Indexed directly by algorithm number */
  48. const struct ssh_digest digests[] = {
  49. { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
  50. { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
  51. { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
  52. { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
  53. { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 },
  54. { SSH_DIGEST_NULL, "NONEMAC", 0, EVP_md_null},
  55. { -1, NULL, 0, NULL },
  56. };
  57. const EVP_MD *
  58. ssh_digest_to_md(int digest_type)
  59. {
  60. switch (digest_type) {
  61. case SSH_DIGEST_SHA1:
  62. return EVP_sha1();
  63. case SSH_DIGEST_SHA256:
  64. return EVP_sha256();
  65. case SSH_DIGEST_SHA384:
  66. return EVP_sha384();
  67. case SSH_DIGEST_SHA512:
  68. return EVP_sha512();
  69. }
  70. return NULL;
  71. }
  72. static const struct ssh_digest *
  73. ssh_digest_by_alg(int alg)
  74. {
  75. if (alg < 0 || alg >= SSH_DIGEST_MAX)
  76. return NULL;
  77. if (digests[alg].id != alg) /* sanity */
  78. return NULL;
  79. if (digests[alg].mdfunc == NULL)
  80. return NULL;
  81. return &(digests[alg]);
  82. }
  83. int
  84. ssh_digest_alg_by_name(const char *name)
  85. {
  86. int alg;
  87. for (alg = 0; digests[alg].id != -1; alg++) {
  88. if (strcasecmp(name, digests[alg].name) == 0)
  89. return digests[alg].id;
  90. }
  91. return -1;
  92. }
  93. const char *
  94. ssh_digest_alg_name(int alg)
  95. {
  96. const struct ssh_digest *digest = ssh_digest_by_alg(alg);
  97. return digest == NULL ? NULL : digest->name;
  98. }
  99. size_t
  100. ssh_digest_bytes(int alg)
  101. {
  102. const struct ssh_digest *digest = ssh_digest_by_alg(alg);
  103. return digest == NULL ? 0 : digest->digest_len;
  104. }
  105. size_t
  106. ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
  107. {
  108. return EVP_MD_CTX_block_size(ctx->mdctx);
  109. }
  110. struct ssh_digest_ctx *
  111. ssh_digest_start(int alg)
  112. {
  113. const struct ssh_digest *digest = ssh_digest_by_alg(alg);
  114. struct ssh_digest_ctx *ret;
  115. if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL))
  116. return NULL;
  117. ret->alg = alg;
  118. if ((ret->mdctx = EVP_MD_CTX_new()) == NULL) {
  119. free(ret);
  120. return NULL;
  121. }
  122. if (EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) {
  123. ssh_digest_free(ret);
  124. return NULL;
  125. }
  126. return ret;
  127. }
  128. int
  129. ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
  130. {
  131. if (from->alg != to->alg)
  132. return SSH_ERR_INVALID_ARGUMENT;
  133. /* we have bcopy-style order while openssl has memcpy-style */
  134. if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx)) {
  135. debug("(!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx))");
  136. return SSH_ERR_LIBCRYPTO_ERROR;
  137. }
  138. return 0;
  139. }
  140. int
  141. ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
  142. {
  143. if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1) {
  144. debug("(EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1)");
  145. return SSH_ERR_LIBCRYPTO_ERROR;
  146. }
  147. return 0;
  148. }
  149. int
  150. ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
  151. {
  152. return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
  153. }
  154. int
  155. ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
  156. {
  157. const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
  158. u_int l = dlen;
  159. if (digest == NULL || dlen > UINT_MAX)
  160. return SSH_ERR_INVALID_ARGUMENT;
  161. if (dlen < digest->digest_len) /* No truncation allowed */
  162. return SSH_ERR_INVALID_ARGUMENT;
  163. if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1) {
  164. debug("(EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1)");
  165. return SSH_ERR_LIBCRYPTO_ERROR;
  166. }
  167. if (l != digest->digest_len) /* sanity */
  168. return SSH_ERR_INTERNAL_ERROR;
  169. return 0;
  170. }
  171. void
  172. ssh_digest_free(struct ssh_digest_ctx *ctx)
  173. {
  174. if (ctx == NULL)
  175. return;
  176. EVP_MD_CTX_free(ctx->mdctx);
  177. freezero(ctx, sizeof(*ctx));
  178. }
  179. int
  180. ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
  181. {
  182. const struct ssh_digest *digest = ssh_digest_by_alg(alg);
  183. u_int mdlen;
  184. if (digest == NULL)
  185. return SSH_ERR_INVALID_ARGUMENT;
  186. if (dlen > UINT_MAX)
  187. return SSH_ERR_INVALID_ARGUMENT;
  188. if (dlen < digest->digest_len)
  189. return SSH_ERR_INVALID_ARGUMENT;
  190. mdlen = dlen;
  191. if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL)) {
  192. debug("(!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL))");
  193. return SSH_ERR_LIBCRYPTO_ERROR;
  194. }
  195. return 0;
  196. }
  197. int
  198. ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
  199. {
  200. return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
  201. }
  202. #endif /* WITH_OPENSSL */