aes-select.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Top-level vtables to select an AES implementation.
  3. */
  4. #include <assert.h>
  5. #include <stdlib.h>
  6. #include "putty.h"
  7. #include "ssh.h"
  8. #include "aes.h"
  9. static ssh_cipher *aes_select(const ssh_cipheralg *alg)
  10. {
  11. const ssh_cipheralg *const *real_algs = (const ssh_cipheralg **)alg->extra;
  12. for (size_t i = 0; real_algs[i]; i++) {
  13. const ssh_cipheralg *alg = real_algs[i];
  14. const struct aes_extra *alg_extra =
  15. (const struct aes_extra *)alg->extra;
  16. if (check_availability(alg_extra))
  17. return ssh_cipher_new(alg);
  18. }
  19. /* We should never reach the NULL at the end of the list, because
  20. * the last non-NULL entry should be software-only AES, which is
  21. * always available. */
  22. unreachable("aes_select ran off the end of its list");
  23. }
  24. #if HAVE_AES_NI
  25. #define IF_NI(...) __VA_ARGS__
  26. #else
  27. #define IF_NI(...)
  28. #endif
  29. #if HAVE_NEON_CRYPTO
  30. #define IF_NEON(...) __VA_ARGS__
  31. #else
  32. #define IF_NEON(...)
  33. #endif
  34. #define AES_SELECTOR_VTABLE(mode_c, id, mode_display, bits, ...) \
  35. static const ssh_cipheralg * \
  36. ssh_aes ## bits ## _ ## mode_c ## _impls[] = { \
  37. IF_NI(&ssh_aes ## bits ## _ ## mode_c ## _ni,) \
  38. IF_NEON(&ssh_aes ## bits ## _ ## mode_c ## _neon,) \
  39. &ssh_aes ## bits ## _ ## mode_c ## _sw, \
  40. NULL, \
  41. }; \
  42. const ssh_cipheralg ssh_aes ## bits ## _ ## mode_c = { \
  43. .new = aes_select, \
  44. .ssh2_id = id, \
  45. .blksize = 16, \
  46. .real_keybits = bits, \
  47. .padded_keybytes = bits/8, \
  48. .text_name = "AES-" #bits " " mode_display \
  49. " (dummy selector vtable)", \
  50. .extra = ssh_aes ## bits ## _ ## mode_c ## _impls, \
  51. __VA_ARGS__ \
  52. }
  53. AES_SELECTOR_VTABLE(cbc, "aes128-cbc", "CBC", 128, .flags = SSH_CIPHER_IS_CBC);
  54. AES_SELECTOR_VTABLE(cbc, "aes192-cbc", "CBC", 192, .flags = SSH_CIPHER_IS_CBC);
  55. AES_SELECTOR_VTABLE(cbc, "aes256-cbc", "CBC", 256, .flags = SSH_CIPHER_IS_CBC);
  56. AES_SELECTOR_VTABLE(sdctr, "aes128-ctr", "SDCTR", 128, );
  57. AES_SELECTOR_VTABLE(sdctr, "aes192-ctr", "SDCTR", 192, );
  58. AES_SELECTOR_VTABLE(sdctr, "aes256-ctr", "SDCTR", 256, );
  59. AES_SELECTOR_VTABLE(gcm, "aes128-gcm@openssh.com", "GCM", 128,
  60. .required_mac = &ssh2_aesgcm_mac,
  61. .flags = SSH_CIPHER_SEPARATE_LENGTH);
  62. AES_SELECTOR_VTABLE(gcm, "aes256-gcm@openssh.com", "GCM", 256,
  63. .required_mac = &ssh2_aesgcm_mac,
  64. .flags = SSH_CIPHER_SEPARATE_LENGTH);
  65. /* 192-bit AES-GCM is included only so that testcrypt can run standard
  66. * test vectors against it. OpenSSH doesn't define a protocol id for
  67. * it. Hence setting its ssh2_id to NULL here, and more importantly,
  68. * leaving it out of aesgcm_list[] below. */
  69. AES_SELECTOR_VTABLE(gcm, NULL, "GCM", 192,
  70. .required_mac = &ssh2_aesgcm_mac,
  71. .flags = SSH_CIPHER_SEPARATE_LENGTH);
  72. static const ssh_cipheralg ssh_rijndael_lysator = {
  73. /* Same as aes256_cbc, but with a different protocol ID */
  74. .new = aes_select,
  75. .ssh2_id = "rijndael-cbc@lysator.liu.se",
  76. .blksize = 16,
  77. .real_keybits = 256,
  78. .padded_keybytes = 256/8,
  79. .flags = SSH_CIPHER_IS_CBC,
  80. .text_name = "AES-256 CBC (dummy selector vtable)",
  81. .extra = ssh_aes256_cbc_impls,
  82. };
  83. static const ssh_cipheralg *const aes_list[] = {
  84. &ssh_aes256_sdctr,
  85. &ssh_aes256_cbc,
  86. &ssh_rijndael_lysator,
  87. &ssh_aes192_sdctr,
  88. &ssh_aes192_cbc,
  89. &ssh_aes128_sdctr,
  90. &ssh_aes128_cbc,
  91. };
  92. const ssh2_ciphers ssh2_aes = { lenof(aes_list), aes_list };
  93. static const ssh_cipheralg *const aesgcm_list[] = {
  94. /* OpenSSH only defines protocol ids for 128- and 256-bit AES-GCM,
  95. * not 192-bit. */
  96. &ssh_aes128_gcm,
  97. &ssh_aes256_gcm,
  98. };
  99. const ssh2_ciphers ssh2_aesgcm = { lenof(aesgcm_list), aesgcm_list };